protected bool ChangeBreasts(Creature target, StringBuilder sb) { bool changed = false; BreastCollectionData oldData = target.genitals.allBreasts.AsReadOnlyData(); if (target.breasts.Count > 1) { changed = target.genitals.RemoveExtraBreastRows() > 0; } CupSize targetSize = EnumHelper.Max(target.genitals.smallestPossibleCupSize, CupSize.D); if (target.breasts[0].cupSize != targetSize) { changed |= target.breasts[0].SetCupSize(targetSize) != 0; } if (changed) { sb.Append(BreastsChangedText(target, oldData)); return(true); } return(false); }
float FromSizeToPrice(CupSize size) { float price = 314f; switch (size) { case CupSize.S: { price = 0.90f; break; } case CupSize.M: { price = 1.00f; break; } case CupSize.L: { price = 1.10f; break; } default: { price = 666f; break; } } return(price); }
static T MakeCoffee <T>(CupSize CupSize) where T : IDrink { BoilWater(3000); var grnds = GrindBeans(new List <CoffeeBeans> { new CoffeeBeans() }); return(PourCoffee <T>(grnds, 2000)); }
public void OrderCoffee(CupSize size) { _currentCup = new CoffeeOrder() { Coffee = new Coffee() { Size = size, Price = CoffeePrice(size) } }; }
static IOrderedDrink MakeCoffee(CupSize CupSize, DrinkName DrinkName) { // Cupsize decides how much water we need. // but CupSize is a property of the drink order var sizes = GetMeasures(CupSize, DrinkName); BoilWater(3000); var grnds = GrindBeans(sizes.Item1); return(null); }
public static string AsText(this CupSize cupSize, bool withArticle = false) { int index = Math.Min(cupText.Length - 1, (byte)cupSize); if (withArticle) { return(articleCupText[index]); } else { return(cupText[index]); } }
private static Tuple <List <CoffeeBeans>, MilliLitres> GetMeasures(CupSize cupSize, DrinkName drinkName) { if (drinkName == DrinkName.Espresso) { switch (cupSize) { case CupSize.Shot: case CupSize.Small: return(Tuple.Create(new List <CoffeeBeans> { { new CoffeeBeans() }, { new CoffeeBeans() } }, new MilliLitres(75))); case CupSize.Large: return(Tuple.Create(new List <CoffeeBeans> { { new CoffeeBeans() }, { new CoffeeBeans() }, { new CoffeeBeans() } }, new MilliLitres(150))); default: throw new ArgumentOutOfRangeException("Unknown Size!"); } } else { switch (cupSize) { case CupSize.Small: return(Tuple.Create(new List <CoffeeBeans> { { new CoffeeBeans() }, { new CoffeeBeans() } }, new MilliLitres(400))); case CupSize.Medium: return(Tuple.Create(new List <CoffeeBeans> { { new CoffeeBeans() }, { new CoffeeBeans() } }, new MilliLitres(500))); case CupSize.Large: return(Tuple.Create(new List <CoffeeBeans> { { new CoffeeBeans() }, { new CoffeeBeans() }, { new CoffeeBeans() } }, new MilliLitres(500))); default: throw new ArgumentOutOfRangeException("Unknown Size!"); } } }
public static string DescribeSize(this CupSize cupSize, Gender gender = Gender.MALE, bool withArticle = false) { //Catch all for dudes. if (cupSize == CupSize.FLAT) { return(gender.HasFlag(Gender.FEMALE) ? "flat" : "manly"); } //Small - A->B if (cupSize <= CupSize.B) { return(Utils.RandomChoice("palmable", "tight", "perky", "baseball-sized")); } //C-D else if (cupSize <= CupSize.D) { return(Utils.RandomChoice("nice", "hand-filling", "well-rounded", "supple", "softball-sized")); } //DD->big EE else if (cupSize < CupSize.F) { return(Utils.RandomChoice("big", "large", "pillowy", "jiggly", "volleyball-sized")); } //F->big FF else if (cupSize < CupSize.G) { return(Utils.RandomChoice("soccerball-sized", "hand-overflowing", "generous", "jiggling")); } //G-> HHH else if (cupSize < CupSize.I) { return(Utils.RandomChoice("basketball-sized", "whorish", "cushiony", "wobbling")); } //I-> KK else if (cupSize < CupSize.L) { return(Utils.RandomChoice("massive motherly", "luscious", "smothering", "prodigious")); } //L-> ZZZ_BIG+ else if (cupSize < CupSize.HYPER_A) { return(Utils.RandomChoice("mountainous", "monumental", "back-breaking", "exercise-ball-sized", "immense")); } //Hyper sizes else { return(Utils.RandomChoice("ludicrously-sized", "hideously large", "absurdly large", "back-breaking", "colossal", "immense")); } }
public CoffeeCup MakeBeverage(CupSize cupSize) { CoffeeCup espresso = new FluentCoffee() .ChooseCupSize(cupSize) .AddBeans(BeanSort.Arabica, 5) .AddWater(20) .Heating(waterTemp => waterTemp >= 95) .ToBeverage(); Console.WriteLine("Your Espresso is ready!"); Console.WriteLine(); Console.WriteLine("You chose a " + cupSize.ToString() + " cup"); Console.WriteLine("It was made with these ingredients: "); return(espresso); }
private decimal CoffeePrice(CupSize size) { switch (size) { case CupSize.Small: return(_appSettings.SmallCoffeePrice); case CupSize.Medium: return(_appSettings.MediumCoffeePrice); case CupSize.Large: return(_appSettings.LargeCoffeePrice); default: throw new ArgumentOutOfRangeException("Invalid coffee size"); } }
public CoffeeCup MakeBeverage(CupSize cupSize) { CoffeeCup americano = new FluentCoffee() .ChooseCupSize(cupSize) .AddBeans(BeanSort.Robusta, 6) .AddWater(15) .Heating(waterTemp => waterTemp >= 95) .AddWater(15) .ToBeverage(); Console.WriteLine("Your Americano is ready"); Console.WriteLine(); Console.WriteLine("You chose a " + cupSize.ToString() + " cup"); Console.WriteLine("It was made with these ingredients: "); return(americano); }
public CoffeeCup MakeBeverage(CupSize cupSize) { CoffeeCup latte = new FluentCoffee() .ChooseCupSize(cupSize) .AddBeans(BeanSort.Robusta, 5) .AddWater(10) .AddMilk(20) .Heating(waterTemp => waterTemp >= 95) .ToBeverage(); Console.WriteLine("Your Latte is ready!"); Console.WriteLine(); Console.WriteLine("You chose a " + cupSize.ToString() + " cup"); Console.WriteLine("It was made with these ingredients: "); return(latte); }
public CupJava MakeBeverage(CupSize cupSize) { CupJava mocha = new FluentCoffee() .ChooseCupSize(cupSize) .AddBeans(BeanSort.Robusta, 6) .AddWater(15) .Heating(waterTemp => waterTemp >= 95) .AddChocolateSyrup(5) .AddMilk(20) .ToBeverage(); Console.WriteLine("Your Mocha is ready!"); Console.WriteLine(); Console.WriteLine("You chose a " + cupSize.ToString() + " cup"); Console.WriteLine("It was made with these ingredients: "); return(mocha); }
public CupJava MakeBeverage(CupSize cupSize) { CupJava cappuccino = new FluentCoffee() .ChooseCupSize(cupSize) .AddBeans(BeanSort.Robusta, 6) .AddWater(15) .Heating(waterTemp => waterTemp >= 95) .AddMilk(10) .AddMilkFoam(6) .ToBeverage(); Console.WriteLine("Your Cappuccino is ready!"); Console.WriteLine(); Console.WriteLine("You chose a " + cupSize.ToString() + " cup"); Console.WriteLine("It was made with these ingredients: "); return(cappuccino); }
protected override void OnEquip(Creature wearer) { wearer.IncreaseLust(5); CupSize largestCup = wearer.genitals.BiggestCupSize(); if (!wearer.wearingUpperGarment) { wearer.HaveGenericTitOrgasm(0, false, false); if (largestCup < CupSize.E_BIG && largestCup >= CupSize.DD) { wearer.IncreaseLust(2); } else if (largestCup >= CupSize.B) { wearer.IncreaseLust(5); } else if (largestCup >= CupSize.A) { wearer.IncreaseLust(10); } else { wearer.IncreaseLust(15); } } if (!wearer.wearingLowerGarment) { var wettest = wearer.genitals.LargestVaginalByWetness(); if (wearer.hasVagina && !wearer.hasCock && wettest.wetness > VaginalWetness.WET) { wearer.IncreaseLust(5); } wearer.HaveGenericAnalOrgasm(false, false); if (wearer.hasVagina) { wearer.HaveGenericVaginalOrgasm(wettest.vaginaIndex, false, false); } } wearer.HaveGenericOralOrgasm(true, false); }
public DarkRoast(CupSize cupSize) { SetSize(cupSize); }
public IFluentCoffee ChooseCupSize(CupSize cupSize) { coffeeCup.CupType = cupSize.ToString(); return(this); }
public Coffee(CupSize size) { Size = size; Price = FromSizeToPrice(size); }
protected internal override string DoTransformation(Creature target, out bool isBadEnd) { isBadEnd = false; //by default, this is 2 rolls at 50%, so a 25% chance of 0 additional tfs, 50% chance of 1 additional tf, 25% chance of 2 additional tfs. //also takes into consideration any perks that increase or decrease tf effectiveness. if you need to roll out your own, feel free to do so. int changeCount = GenerateChangeCount(target, new int[] { 2, 2 }); int remainingChanges = changeCount; StringBuilder sb = new StringBuilder(); //For all of these, any text regarding the transformation should be instead abstracted out as an abstract string function. append the result of this abstract function //to the string builder declared above (aka sb.Append(FunctionCall(variables));) string builder is just a fancy way of telling the compiler that you'll be creating a //long string, piece by piece, so don't do any crazy optimizations first. //the initial text for starting the transformation. feel free to add additional variables to this if needed. //Add any free changes here - these can occur even if the change count is 0. these include things such as change in stats (intelligence, etc) //change in height, hips, and/or butt, or other similar stats. double crit = 0; if (Utils.Rand(100) < 15) { crit = Utils.Rand(20) / 10.0 + 2; } bool hasCrit() => crit > 1; sb.Append(InitialTransformationText(target, crit)); //STAT CHANGES - TOU SPE INT RANDOM CHANCE, LIB LUST COR ALWAYS UPPED target.DeltaCreatureStats(lib: 1 + Utils.Rand(2), lus: 5 + Utils.Rand(10), corr: 1 + Utils.Rand(5)); if (target.relativeToughness < 70 && Utils.Rand(3) == 0) { double delta = target.ChangeToughness(crit); sb.Append(IncreasedToughnessText(crit, delta)); } if (target.relativeSpeed > 30 && Utils.Rand(7) == 0) { double loss = target.DecreaseSpeed(crit); sb.Append(DecreasedSpeedText(crit, loss)); } if (target.relativeIntelligence < 60 && Utils.Rand(7) == 0) { double delta = target.ChangeIntelligence(crit); sb.Append(IncreasedIntelligenceText(crit, delta)); } //handle edge case where we start at 0. if (remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } //Non-free changes. //if (--remainingChanges <= 0) return ApplyChangesAndReturn(target, sb, changeCount - remainingChanges); //MUTATIONZZZZZ //PRE-CHANGES: become biped, remove horns, remove wings, give human tongue, remove claws, remove antennea //no claws if (Utils.Rand(4) == 0 && target.arms.hands.isClaws) { ArmData oldData = target.arms.AsReadOnlyData(); if (target.RestoreArms()) { sb.Append(RestoredArmsText(target, oldData)); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } } //remove antennae if (target.antennae.type != AntennaeType.NONE && Utils.Rand(3) == 0) { AntennaeData oldData = target.antennae.AsReadOnlyData(); target.RestoreAntennae(); sb.Append(RestoredAntennaeText(target, oldData)); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //remove horns if (target.horns.type != HornType.NONE && Utils.Rand(3) == 0) { HornData oldData = target.horns.AsReadOnlyData(); target.RestoreHorns(); sb.Append(RestoredHornsText(target, oldData)); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //remove wings if ((target.wings.type != WingType.NONE || target.back.type == BackType.SHARK_FIN) && Utils.Rand(3) == 0) { BackData oldBack = target.back.AsReadOnlyData(); if (target.back.type == BackType.SHARK_FIN) { target.RestoreBack(); } WingData oldWings = target.wings.AsReadOnlyData(); target.RestoreWings(); sb.Append(RestoredBackAndWings(target, oldWings, oldBack)); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //give human tongue if (target.tongue.type != TongueType.HUMAN && Utils.Rand(3) == 0) { //MOD NOTE: this was incorrect - this actually was === (equal with strict typechecking) instead of = (assign). so this was an implicit bool. //this is part of the reason why the rework forces all value updates as function calls. the more you know. TongueData oldData = target.tongue.AsReadOnlyData(); target.RestoreTongue(); sb.Append(RestoredTongueText(target, oldData)); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //remove non-wolf eyes if (Utils.Rand(3) == 0 && target.eyes.type != EyeType.HUMAN && target.eyes.type != EyeType.WOLF) { EyeData oldData = target.eyes.AsReadOnlyData(); target.RestoreEyes(); sb.Append(RestoredEyesText(target, oldData)); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //normal legs if (target.lowerBody.type != LowerBodyType.WOLF && Utils.Rand(4) == 0) { LowerBodyData oldData = target.lowerBody.AsReadOnlyData(); target.RestoreLowerBody(); sb.Append(RestoredLowerBodyText(target, oldData)); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //normal arms if (Utils.Rand(4) == 0) { ArmData oldData = target.arms.AsReadOnlyData(); target.RestoreArms(); sb.Append(RestoredArmsText(target, oldData)); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } HairData oldHair = target.hair.AsReadOnlyData(); //remove feather hair if (Utils.Rand(4) == 0 && RemoveFeatheryHair(target)) { sb.Append(RemovedFeatheryHairText(target, oldHair)); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //remove basilisk hair if (Utils.Rand(4) == 0 && target.hair.IsBasiliskHair()) { HairData oldData = target.hair.AsReadOnlyData(); target.RestoreHair(); target.hair.SetHairLength(0); target.hair.ResumeNaturalGrowth(); sb.Append(RemovedBasiliskHair(target, oldData)); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //MUTATIONZ AT ANY TIME: wolf dick, add/decrease breasts, decrease breast size if above D //get a wolf dick //if ya genderless we give ya a dick cuz we nice like that //MOD: Now respects hyper happy. if (target.gender == Gender.GENDERLESS && !hyperHappy) { target.genitals.AddCock(CockType.WOLF, Utils.Rand(4) + 4, Utils.Rand(8) / 4.0 + 0.25, 1.5); sb.Append(BecameMaleByGrowingCock(target)); target.DeltaCreatureStats(lib: 3, sens: 2, lus: 25); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //if ya got a dick that's ok too we'll change it to wolf //MOD NOTE: but only if you don't only have wolf cocks, of course (because if they are all wolf cocks, we can't make anything wolf cocks, duh). if (target.hasCock && !target.genitals.OnlyHasCocksOfType(CockType.WOLF) && Utils.RandBool()) { //MOD NOTE: no longer shamelessly copy/pasted from dog c**k, because we have better ways of looping in C#. C**k firstNonWolf = target.cocks.First(x => x.type != CockType.WOLF); CockData oldData = firstNonWolf.AsReadOnlyData(); //Select first non-wolf c**k //MOD: now using type description because we can, so the fact this used generic is irrelevant now :) if (firstNonWolf.type == CockType.HORSE) { //horses get changes if (firstNonWolf.length > 6) { firstNonWolf.DecreaseLength(2); } else { firstNonWolf.DecreaseLength(.5); } firstNonWolf.IncreaseThickness(.5); } target.DeltaCreatureStats(sens: 3, lus: 5 * crit); target.genitals.UpdateCockWithKnot(firstNonWolf, CockType.WOLF, 1.5); firstNonWolf.IncreaseThickness(2); sb.Append(ChangedCockToWolf(target, oldData, oldData.cockIndex)); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //titties for those who got titties //wolfs have 8 nips so, 4 rows max. fen has no power here I'm making a wolf not a dog. //MOD: still stolen shamelessly from dog and updated, but now with the modern format. woo! //MOD: if breasts can be updated (not flat) and we flip a coin. if (target.genitals.BiggestCupSize() > CupSize.FLAT && Utils.RandBool()) { if (target.breasts.Count < 4) { byte breastCount = (byte)target.breasts.Count; BreastCollectionData oldBreastData = target.genitals.allBreasts.AsReadOnlyData(); //in vanilla code, we had some strange checks here that required the first row (and only the first row) be a certain size. //now, we check all the rows, but no longer require any of them to be a certain size. instead, if it's not the right size, we make it that size, //then add the row. so, for two rows, your first row must be at least a B-Cup. for 3: first must be a C cup, second an A cup. //if we supported 4 rows, it'd be D, B, A. for (int x = 0; x < target.breasts.Count; x++) { CupSize requiredSize = (CupSize)(byte)(target.breasts.Count - x); if (x == 0) { requiredSize++; } if (target.breasts[x].cupSize < requiredSize) { target.breasts[x].SetCupSize(requiredSize); } } target.genitals.AddBreastRow(target.breasts[breastCount - 1].cupSize.ByteEnumSubtract(1)); bool doCrit = false, uberCrit = false; if (target.breasts.Count == 2) { target.IncreaseCreatureStats(lus: 5, sens: 6); } else if (hasCrit()) { doCrit = true; if (crit > 2) { target.IncreaseCreatureStats(sens: 6, lus: 15); uberCrit = true; } else { target.IncreaseCreatureStats(sens: 3, lus: 10); } } sb.Append(UpdateAndGrowAdditionalRowText(target, oldBreastData, doCrit, uberCrit)); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } else { BreastCollectionData oldBreastData = target.genitals.allBreasts.AsReadOnlyData(); //only call the normalize text if we actually did anything. related, anthro breasts now returns a bool. thanks, fox tfs. if (target.genitals.AnthropomorphizeBreasts()) { sb.Append(NormalizedBreastSizeText(target, oldBreastData)); } } } //Remove a breast row if over 4. afaik this should never happen. if (target.breasts.Count > 4 && Utils.Rand(3) == 0) { var oldData = target.breasts[target.breasts.Count - 1].AsReadOnlyData(); target.genitals.RemoveBreastRows(1); sb.Append(RemovedExcessRow(target, oldData)); } //Grow breasts if has v****a and has no breasts/nips //Shrink breasts if over D-cup CupSize targetSize = EnumHelper.Max(target.genitals.smallestPossibleCupSize, CupSize.D); if (!hyperHappy && target.genitals.BiggestCupSize() > targetSize && Utils.Rand(3) == 0) { BreastCollectionData oldCollection = target.genitals.allBreasts.AsReadOnlyData(); bool changedAnything = false; foreach (Breasts row in target.breasts) { //If this row is over threshhold if (row.cupSize > targetSize) { //Big change if (row.cupSize > CupSize.EE_BIG) { changedAnything |= row.ShrinkBreasts((byte)(2 + Utils.Rand(3))) > 0; } //Small change else { changedAnything |= row.ShrinkBreasts() > 0; } //Increment changed rows } } //Count shrinking if (changedAnything) { sb.Append(ShrunkRowsText(target, oldCollection)); remainingChanges--; if (remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } } //MUTATIONZ LEVEL 1: fur, stop hair growth, ears, tail //Gain fur if (Utils.Rand(5) == 0 && !target.body.IsFurBodyType()) { BodyData oldData = target.body.AsReadOnlyData(); Species.WOLF.GetRandomFurColors(out FurColor primary, out FurColor underbody); if (FurColor.IsNullOrEmpty(underbody)) { target.UpdateBody(BodyType.UNDERBODY_FUR, primary); } else { target.UpdateBody(BodyType.UNDERBODY_FUR, primary, underbody); } sb.Append(UpdateBodyText(target, oldData)); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //Ears time if (Utils.Rand(3) == 0 && target.ears.type != EarType.WOLF) { EarData oldData = target.ears.AsReadOnlyData(); target.UpdateEars(EarType.WOLF); sb.Append(UpdateEarsText(target, oldData)); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //Wolf tail if (Utils.Rand(3) == 0 && target.tail.type != TailType.WOLF) { TailData oldData = target.tail.AsReadOnlyData(); target.UpdateTail(TailType.WOLF); sb.Append(UpdateTailText(target, oldData)); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //Sets hair normal if (target.hair.type != HairType.NORMAL && Utils.Rand(3) == 0) { HairData oldData = target.hair.AsReadOnlyData(); target.RestoreHair(); sb.Append(RestoreHairText(target, oldData)); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //MUTATIONZ LEVEL 2: fur->arms fur+tail+ears->face stophair->nohair fur+tail->legs //gain wolf face if (target.face.type != FaceType.WOLF && target.ears.type == EarType.WOLF && target.tail.type == TailType.WOLF && target.body.IsFurBodyType() && Utils.Rand(5) == 0) { FaceData oldData = target.face.AsReadOnlyData(); target.UpdateFace(FaceType.WOLF); sb.Append(UpdateFaceText(target, oldData)); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //legz if (target.lowerBody.legCount == 2 && target.lowerBody.type != LowerBodyType.WOLF && target.tail.type == TailType.WOLF && target.body.IsFurBodyType() && Utils.Rand(4) == 0) { //Hooman feets //Hooves -> Paws LowerBodyData oldData = target.lowerBody.AsReadOnlyData(); target.UpdateLowerBody(LowerBodyType.WOLF); sb.Append(UpdateLowerBodyText(target, oldData)); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //MUTATIONZ LEVEL 3: face->eyes if (target.eyes.type != EyeType.WOLF && target.face.type == FaceType.WOLF && Utils.Rand(4) == 0) { EyeData oldData = target.eyes.AsReadOnlyData(); target.UpdateEyes(EyeType.WOLF); sb.Append(UpdateEyesText(target, oldData)); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //MISC CRAP //Neck restore if (target.neck.type != NeckType.HUMANOID && Utils.Rand(4) == 0) { NeckData oldData = target.neck.AsReadOnlyData(); target.RestoreNeck(); sb.Append(RestoredNeckText(target, oldData)); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //Rear body restore if (!target.back.isDefault && Utils.Rand(5) == 0) { BackData oldData = target.back.AsReadOnlyData(); target.RestoreBack(); sb.Append(RestoredBackText(target, oldData)); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //Ovi perk loss if (target.womb.canRemoveOviposition && Utils.Rand(5) == 0) { target.womb.ClearOviposition(); sb.Append(ClearOvipositionText(target)); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } if (Utils.Rand(3) == 0) { var res = target.build.ChangeMuscleToneToward(100, 4); sb.Append(AdjustToneText(target, 4, res)); } if (Utils.Rand(3) == 0) { var adjustedAmount = target.build.ChangeThicknessToward(75, 3); sb.Append(AdjustThicknessText(target, adjustedAmount)); } //this is the fallthrough that occurs when a tf item goes through all the changes, but does not proc enough of them to exit early. it will apply however many changes //occurred, then return the contents of the stringbuilder. return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); }
protected internal override string DoTransformation(Creature target, out bool isBadEnd) { isBadEnd = false; int changeCount = GenerateChangeCount(target, new int[] { 2, 2 }); int remainingChanges = changeCount; StringBuilder sb = new StringBuilder(); //the initial text for starting the transformation. feel free to add additional variables to this if needed. sb.Append(InitialTransformationText(target)); //Add any free changes here - these can occur even if the change count is 0. these include things such as change in stats (intelligence, etc) //change in height, hips, and/or butt, or other similar stats. //this will handle the edge case where the change count starts out as 0. if (remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } //Any transformation related changes go here. these typically cost 1 change. these can be anything from body parts to gender (which technically also changes body parts, //but w/e). You are required to make sure you return as soon as you've applied changeCount changes, but a single line of code can be applied at the end of a change to do //this for you. //paste this line after any tf is applied, and it will: automatically decrement the remaining changes count. if it becomes 0 or less, apply the total number of changes //underwent to the target's change count (if applicable) and then return the StringBuilder content. //if (--remainingChanges <= 0) return ApplyChangesAndReturn(target, sb, changeCount - remainingChanges); //----------------------- // MAJOR TRANSFORMATIONS //----------------------- //1st priority: Change lower body to bipedal. if (Utils.Rand(4) == 0) { LowerBodyData oldData = target.lowerBody.AsReadOnlyData(); target.RestoreLowerBody(); sb.Append(RestoredLowerBodyText(target, oldData)); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //Remove Oviposition Perk if (target.womb.canRemoveOviposition && Utils.Rand(5) == 0) { target.womb.ClearOviposition(); sb.Append(ClearOvipositionText(target)); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //Remove Incorporeality Perk, if not permanent if (target.HasPerk <Incorporeal>() && Utils.Rand(4) == 0) { target.RemovePerk <Incorporeal>(); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //Restore neck if (target.neck.type != NeckType.HUMANOID && Utils.Rand(5) == 0) { NeckData oldData = target.neck.AsReadOnlyData(); target.RestoreNeck(); sb.Append(RestoredNeckText(target, oldData)); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //Rear body restore if (!target.back.isDefault && Utils.Rand(5) == 0) { BackData oldData = target.back.AsReadOnlyData(); target.RestoreBack(); sb.Append(RestoredBackText(target, oldData)); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //-Skin color change – light, fair, olive, dark, ebony, mahogany, russet if (!Species.HUMAN.availableTones.Contains(target.body.primarySkin.tone) && Utils.Rand(5) == 0) { target.body.ChangeAllSkin(Utils.RandomChoice(Species.HUMAN.availableTones)); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //Change skin to normal if (target.body.type != BodyType.HUMANOID && (target.ears.type == EarType.HUMAN || target.ears.type == EarType.ELFIN) && Utils.Rand(4) == 0) { BodyData oldData = target.body.AsReadOnlyData(); target.RestoreBody(); sb.Append(RestoredBodyText(target, oldData)); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //Restore arms to become human arms again if (Utils.Rand(4) == 0) { ArmData oldData = target.arms.AsReadOnlyData(); target.RestoreArms(); sb.Append(RestoredArmsText(target, oldData)); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //----------------------- // MINOR TRANSFORMATIONS //----------------------- //-Human face if (target.face.type != FaceType.HUMAN && Utils.Rand(4) == 0) { FaceData oldData = target.face.AsReadOnlyData(); target.RestoreFace(); sb.Append(RestoreFaceText(target, oldData)); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //-Human tongue if (target.tongue.type != TongueType.HUMAN && Utils.Rand(4) == 0) { TongueData oldData = target.tongue.AsReadOnlyData(); target.RestoreTongue(); sb.Append(RestoreTongueText(target, oldData)); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //Remove odd eyes if (Utils.Rand(5) == 0 && target.eyes.type != EyeType.HUMAN) { EyeData oldData = target.eyes.AsReadOnlyData(); target.RestoreEyes(); sb.Append(RestoredEyesText(target, oldData)); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //-Gain human ears (If you have human face) if (target.ears.type != EarType.HUMAN && target.face.type == FaceType.HUMAN && Utils.Rand(4) == 0) { EarData oldData = target.ears.AsReadOnlyData(); target.RestoreEar(); sb.Append(RestoreEarsText(target, oldData)); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //Removes gills if (Utils.Rand(4) == 0 && !target.gills.isDefault) { GillData oldData = target.gills.AsReadOnlyData(); target.RestoreGills(); sb.Append(RestoredGillsText(target, oldData)); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //Nipples Turn Back: if (target.genitals.hasBlackNipples && Utils.Rand(3) == 0) { target.genitals.SetBlackNipples(false); } //Remove extra nipples if (target.genitals.hasQuadNipples && Utils.Rand(3) == 0) { target.genitals.SetQuadNipples(false); } //Hair turns normal //Restart hair growth, if hair's normal but growth isn't on. Or just over turning hair normal. The power of rng. if ((target.hair.type != HairType.NORMAL || target.hair.growthArtificallyDisabled) && Utils.Rand(3) == 0) { target.UpdateHair(HairType.NORMAL); if (target.hair.growthArtificallyDisabled) { target.hair.SetHairGrowthStatus(true); } if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //----------------------- // EXTRA PARTS REMOVAL //----------------------- //Removes antennae if (target.antennae.type != AntennaeType.NONE && Utils.Rand(3) == 0) { AntennaeData oldData = target.antennae.AsReadOnlyData(); target.RestoreAntennae(); sb.Append(RestoredAntennaeText(target, oldData)); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //Removes horns if ((target.horns.type != HornType.NONE) && Utils.Rand(5) == 0) { HornData oldData = target.horns.AsReadOnlyData(); target.RestoreHorns(); sb.Append(RestoredHornsText(target, oldData)); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //Removes wings if (target.wings.type != WingType.NONE && Utils.Rand(5) == 0) { WingData oldData = target.wings.AsReadOnlyData(); target.RestoreWings(); sb.Append(RestoredWingsText(target, oldData)); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //Removes tail if (target.tail.type != TailType.NONE && Utils.Rand(5) == 0) { TailData oldData = target.tail.AsReadOnlyData(); target.RestoreTail(); sb.Append(RestoredTailText(target, oldData)); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //Increase height up to 4ft 10in. if (Utils.Rand(2) == 0 && target.build.heightInInches < 58) { int temp = Utils.Rand(5) + 3; //Flavor texts. Flavored like 1950's cigarettes. Yum. target.build.IncreaseHeight((byte)temp); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //Decrease height down to a maximum of 6ft 2in. if (Utils.Rand(2) == 0 && target.build.heightInInches > 74) { target.build.DecreaseHeight((byte)(3 + Utils.Rand(5))); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //----------------------- // SEXUAL TRANSFORMATIONS //----------------------- //Remove additional cocks if (target.cocks.Count > 1 && Utils.Rand(3) == 0) { target.RemoveCock(); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //Remove additional balls/remove uniball if (target.balls.hasBalls && (target.balls.count != 2 || target.balls.uniBall) && Utils.Rand(3) == 0) { if (target.balls.size > 2) { if (target.balls.size > 5) { target.balls.ShrinkBalls((byte)(1 + Utils.Rand(3))); } target.balls.ShrinkBalls(1); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } else if (target.balls.count > 2) { target.balls.RemoveExtraBalls(); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } else //if (target.balls.count == 1 || target.balls.uniBall) { target.balls.MakeStandard(); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } } //remove second v****a. if (target.vaginas.Count > 1 && Utils.Rand(3) == 0) { target.genitals.RemoveExtraVaginas(); } //Change c**k back to normal if (target.hasCock && !target.genitals.OnlyHasCocksOfType(CockType.HUMAN) && Utils.Rand(3) == 0) { //Select first non-human c**k C**k firstNonHuman = target.cocks.First(x => x.type != CockType.HUMAN); target.genitals.UpdateCock(firstNonHuman, CockType.HUMAN); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } C**k longest = target.genitals.LongestCock(); double targetSize = Math.Max(7, target.genitals.minimumCockLength); //Shrink oversized cocks if (target.hasCock && longest.length > targetSize && Utils.Rand(3) == 0) { longest.DecreaseLength((Utils.Rand(10) + 2) / 10.0); if (longest.girth > 1) { longest.DecreaseThickness((Utils.Rand(4) + 1) / 10.0); } if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //Remove additional breasts if (target.breasts.Count > 1 && Utils.Rand(3) == 0) { target.RemoveExtraBreastRows(); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } Breasts biggestCup = target.genitals.LargestBreast(); CupSize targetCup = EnumHelper.Max(CupSize.D, target.genitals.smallestPossibleFemaleCupSize); //Shrink t**s! if (Utils.Rand(3) == 0 && biggestCup.cupSize > targetCup) { foreach (Breasts t**s in target.breasts) { t**s.ShrinkBreasts(); } if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //Change v****a back to normal if (Utils.Rand(3) == 0 && target.hasVagina && !target.genitals.OnlyHasVaginasOfType(VaginaType.defaultValue)) { foreach (V****a vag in target.vaginas) { target.genitals.RestoreVagina(vag); } if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } VaginalWetness targetWetness = EnumHelper.Max(VaginalWetness.WET, target.genitals.minVaginalWetness); //Reduce wetness down to a minimum of 2 if (Utils.Rand(3) == 0 && target.hasVagina && target.genitals.LargestVaginalWetness() > targetWetness) { foreach (V****a vag in target.vaginas) { if (vag.wetness > targetWetness) { vag.DecreaseWetness(); } } if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //Fertility Decrease: if (target.hasVagina && target.fertility.baseFertility > 10 && Utils.Rand(3) == 0) { //High fertility: //Average fertility: target.fertility.DecreaseFertility((byte)(1 + Utils.Rand(3))); if (target.fertility.baseFertility < 10) { target.fertility.SetFertility(10); } if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //Cum Multiplier Decrease: if (target.hasCock && target.genitals.cumMultiplier > 5 && Utils.Rand(3) == 0) { target.genitals.DecreaseCumMultiplier(1 + (Utils.Rand(20) / 10.0)); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //Anal wetness decrease if (target.ass.wetness > 0 && Utils.Rand(3) == 0) { target.ass.DecreaseWetness(); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //this is the fallthrough that occurs when a tf item goes through all the changes, but does not proc enough of them to exit early. it will apply however many changes //occurred, then return the contents of the stringbuilder. return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); }
public Americano(CupSize size) : base(size) { }
protected internal override string DoTransformation(Creature target, out bool isBadEnd) { isBadEnd = false; //by default, this is 2 rolls at 50%, so a 25% chance of 0 additional tfs, 50% chance of 1 additional tf, 25% chance of 2 additional tfs. //also takes into consideration any perks that increase or decrease tf effectiveness. if you need to roll out your own, feel free to do so. int changeCount = GenerateChangeCount(target, new int[] { 2, 2, 3 }, isEnhanced ? 3 : 1); int totalChanges = 0; StringBuilder sb = new StringBuilder(); //For all of these, any text regarding the transformation should be instead abstracted out as an abstract string function. append the result of this abstract function //to the string builder declared above (aka sb.Append(FunctionCall(variables));) string builder is just a fancy way of telling the compiler that you'll be creating a //long string, piece by piece, so don't do any crazy optimizations first. //the initial text for starting the transformation. feel free to add additional variables to this if needed. sb.Append(InitialTransformationText(target)); //Add any free changes here - these can occur even if the change count is 0. these include things such as change in stats (intelligence, etc) //change in height, hips, and/or butt, or other similar stats. //this will handle the edge case where the change count starts out as 0. //paste this line after any tf is applied, and it will: automatically decrement the remaining changes count. if it becomes 0 or less, apply the total number of changes //underwent to the target's change count (if applicable) and then return the StringBuilder content. //if (--remainingChanges <= 0) return ApplyChangesAndReturn(target, sb, changeCount - remainingChanges); //STATS //Increase player str: if (target.strength < 60 && Utils.Rand(3) == 0) { double delta = target.IncreaseStrength((60 - target.strength) / 10.0); sb.Append(StrengthUpText(delta)); } //Increase player tou: if (target.toughness < 60 && Utils.Rand(3) == 0) { double delta = target.IncreaseToughness((60 - target.toughness) / 10.0); sb.Append(ToughnessUpText(delta)); } //Decrease player spd if it is over 30: if (target.relativeSpeed > 30 && target.speed > 30 && Utils.Rand(3) == 0) { double decrease = target.DecreaseSpeed((target.speed - 30) / 10.0); sb.Append(SpeedDownText(decrease)); } //Increase Corr, up to a max of 50. //this is silent, apparently. if (!isPurified && target.corruption < 50) { target.IncreaseCorruptionBy((50 - target.corruption) / 10.0); } if (totalChanges >= changeCount) { return(FinalizeTransformation(target, sb, totalChanges)); } //Sex bits - Duderiffic if (target.cocks.Count > 0 && Utils.Rand(2) == 0 && !hyperHappy) { //If the player has at least one dick, decrease the size of each slightly, C**k biggest = target.genitals.LongestCock(); CockData preChange = biggest.AsReadOnlyData(); if (biggest.DecreaseLengthAndCheckIfNeedsRemoval(Utils.Rand(3) + 1)) { target.genitals.RemoveCock(biggest); if (target.cocks.Count == 0 && !target.hasVagina) { BallsData oldBalls = target.balls.AsReadOnlyData(); target.AddVagina(0.25); target.genitals.RemoveAllBalls(); sb.Append(MadeFemale(target, preChange, oldBalls)); } else { sb.Append(ShrunkOneCock(target, preChange, true)); } } else { sb.Append(ShrunkOneCock(target, preChange, false)); } if (++totalChanges >= changeCount) { return(FinalizeTransformation(target, sb, totalChanges)); } } //Sex bits - girly bool boobsGrew = false; //Increase player's breast size, if they are FF or bigger //do not increase size, but do the other actions: CupSize biggestCup = target.genitals.BiggestCupSize(); if ((biggestCup < CupSize.DD || (!isPurified && biggestCup < CupSize.FF)) && (isEnhanced || Utils.Rand(3) == 0)) { BreastData oldBreasts = target.breasts[0].AsReadOnlyData(); if (target.breasts[0].GrowBreasts((byte)(1 + Utils.Rand(3))) > 0) { boobsGrew = true; sb.Append(GrewFirstBreastRow(target, oldBreasts)); if (++totalChanges >= changeCount) { return(FinalizeTransformation(target, sb, totalChanges)); } } target.DeltaCreatureStats(sens: .5); } //Remove feathery hair HairData oldHair = target.hair.AsReadOnlyData(); if (base.RemoveFeatheryHair(target)) { sb.Append(RemovedFeatheryHairText(target, oldHair)); if (++totalChanges >= changeCount) { return(FinalizeTransformation(target, sb, totalChanges)); } } //refresh the biggest cup size because we may have grown some breasts earlier. biggestCup = target.genitals.BiggestCupSize(); //If breasts are D or bigger and are not lactating, they also start lactating: if (biggestCup >= CupSize.D && !target.genitals.isLactating && (isEnhanced || boobsGrew || Utils.Rand(3) == 0)) { BreastData preLactation = target.breasts[0].AsReadOnlyData(); target.genitals.StartLactating(); sb.Append(StartedLactatingText(target, preLactation)); if (++totalChanges >= changeCount) { return(FinalizeTransformation(target, sb, totalChanges)); } target.DeltaCreatureStats(sens: .5); } //Quad nipples and other 'special isEnhanced things. if (isEnhanced) { //QUAD DAMAGE! if (!target.genitals.hasQuadNipples) { BreastCollectionData oldBreasts = target.genitals.allBreasts.AsReadOnlyData(); target.genitals.SetQuadNipples(true); sb.Append(GrantQuadNippleText(target, oldBreasts)); if (++totalChanges >= changeCount) { return(FinalizeTransformation(target, sb, totalChanges)); } } else if (target.genitals.isLactating) { BreastCollectionData oldBreasts = target.genitals.allBreasts.AsReadOnlyData(); target.genitals.BoostLactation(2.5); double delta = 0; if (target.genitals.nippleLength < 1 || (target.genitals.nippleLength < 1.5 && !isPurified)) { delta = target.genitals.GrowNipples(0.25); target.DeltaCreatureStats(sens: .5); } sb.Append(BoostedLactationText(target, oldBreasts, delta)); if (++totalChanges >= changeCount) { return(FinalizeTransformation(target, sb, totalChanges)); } } } //If breasts are already lactating and the player is not lactating beyond a reasonable level, they start lactating more: else { if (target.genitals.isLactating && (target.genitals.lactationStatus < LactationStatus.MODERATE || (!isPurified && target.genitals.lactationStatus < LactationStatus.STRONG)) && (isEnhanced || Utils.Rand(3) == 0)) { BreastCollectionData oldBreasts = target.genitals.allBreasts.AsReadOnlyData(); double delta = 0; target.genitals.BoostLactation(0.75); if (target.genitals.nippleLength < 1 || (target.genitals.nippleLength < 1.5 && !isPurified)) { delta = target.genitals.GrowNipples(0.25); target.DeltaCreatureStats(sens: .5); } sb.Append(BoostedLactationText(target, oldBreasts, delta)); if (++totalChanges >= changeCount) { return(FinalizeTransformation(target, sb, totalChanges)); } } else if (isPurified && target.genitals.lactationStatus >= LactationStatus.STRONG) { BreastCollectionData oldData = target.genitals.allBreasts.AsReadOnlyData(); target.DeltaCreatureStats(sens: .5); target.genitals.BoostLactation(-1); sb.Append(BoostedLactationText(target, oldData, 0)); if (++totalChanges >= changeCount) { return(FinalizeTransformation(target, sb, totalChanges)); } } } //If breasts are lactating at a fair level //and the player has not received this status, //apply an effect where the player really wants //to give their milk to other creatures //(capable of getting them addicted): biggestCup = target.genitals.BiggestCupSize(); if (!target.HasPerk <Feeder>() && target.genitals.lactationStatus >= LactationStatus.MODERATE && Utils.Rand(2) == 0 && biggestCup >= CupSize.DD && target.IsCorruptEnough(35)) { target.perks.AddPerk <Feeder>(); sb.Append(GainedFeederPerk(target)); if (++totalChanges >= changeCount) { return(FinalizeTransformation(target, sb, totalChanges)); } } //UNFINISHED //If player has addictive quality and drinks pure version, removes addictive quality. //if the player has a v****a and it is tight, it loosens. if (target.hasVagina) { VaginalLooseness targetLooseness = EnumHelper.Min(VaginalLooseness.LOOSE, target.genitals.maxVaginalLooseness); V****a tightest = target.genitals.TightestVagina(); if (tightest.looseness < targetLooseness && Utils.Rand(2) == 0) { VaginaData preLoosened = tightest.AsReadOnlyData(); tightest.IncreaseLooseness(2); sb.Append(LoosenedTwatText(target, preLoosened)); if (++totalChanges >= changeCount) { return(FinalizeTransformation(target, sb, totalChanges)); } target.DeltaCreatureStats(lus: 10); } } //Neck restore if (target.neck.type != NeckType.HUMANOID && Utils.Rand(4) == 0) { NeckData oldData = target.neck.AsReadOnlyData(); target.RestoreNeck(); sb.Append(RestoredNeckText(target, oldData)); if (++totalChanges >= changeCount) { return(FinalizeTransformation(target, sb, totalChanges)); } } //Rear body restore if (target.back.type != BackType.SHARK_FIN && Utils.Rand(5) == 0) { BackData oldData = target.back.AsReadOnlyData(); target.RestoreBack(); sb.Append(RestoredBackText(target, oldData)); if (++totalChanges >= changeCount) { return(FinalizeTransformation(target, sb, totalChanges)); } } //Ovi perk loss if (!isPurified && target.womb.canRemoveOviposition && Utils.Rand(5) == 0) { target.womb.ClearOviposition(); sb.Append(ClearOvipositionText(target)); if (++totalChanges >= changeCount) { return(FinalizeTransformation(target, sb, totalChanges)); } } //General Appearance (Tail -> Ears -> Paws(fur stripper) -> Face -> Horns //Give the player a bovine tail, same as the minotaur if (!isPurified && target.tail.type != TailType.COW && Utils.Rand(3) == 0) { TailData oldData = target.tail.AsReadOnlyData(); target.UpdateTail(TailType.COW); sb.Append(ChangedTailText(target, oldData)); if (++totalChanges >= changeCount) { return(FinalizeTransformation(target, sb, totalChanges)); } } //Give the player bovine ears, same as the minotaur if (!isPurified && target.ears.type != EarType.COW && Utils.Rand(4) == 0 && target.tail.type == TailType.COW) { EarData oldEars = target.ears.AsReadOnlyData(); target.UpdateEars(EarType.COW); sb.Append(ChangedEarsText(target, oldEars)); if (++totalChanges >= changeCount) { return(FinalizeTransformation(target, sb, totalChanges)); } } //If the player is under 7 feet in height, increase their height, similar to the minotaur if (((isEnhanced && target.build.heightInInches < 96) || target.build.heightInInches < 84) && Utils.Rand(2) == 0) { int temp = Utils.Rand(5) + 3; //Slow rate of growth near ceiling if (target.build.heightInInches > 74) { temp = (int)Math.Floor(temp / 2.0); } //Never 0 if (temp == 0) { temp = 1; } byte delta = target.build.IncreaseHeight((byte)temp); sb.Append(GrowTaller(target, delta)); if (++totalChanges >= changeCount) { return(FinalizeTransformation(target, sb, totalChanges)); } } //Give the player hoofs, if the player already has hoofs STRIP FUR if (!isPurified && target.lowerBody.type != LowerBodyType.HOOVED && target.ears.type == EarType.COW) { if (Utils.Rand(3) == 0) { var oldData = target.lowerBody.AsReadOnlyData(); target.UpdateLowerBody(LowerBodyType.HOOVED); sb.Append(ChangedLowerBodyText(target, oldData)); if (++totalChanges >= changeCount) { return(FinalizeTransformation(target, sb, totalChanges)); } } } //If the player's face is non-human, they gain a human face if (!isEnhanced && target.lowerBody.type == LowerBodyType.HOOVED && target.face.type != FaceType.HUMAN && Utils.Rand(4) == 0) { //Remove face before fur! var oldData = target.face.AsReadOnlyData(); target.RestoreFace(); sb.Append(RestoredFaceText(target, oldData)); if (++totalChanges >= changeCount) { return(FinalizeTransformation(target, sb, totalChanges)); } } //isEnhanced get shitty fur var targetFur = new FurColor(HairFurColors.BLACK, HairFurColors.WHITE, FurMulticolorPattern.SPOTTED); if (isEnhanced && (!target.body.IsFurBodyType() || !target.body.mainEpidermis.fur.Equals(targetFur))) { var oldData = target.body.AsReadOnlyData(); if (target.body.type == BodyType.SIMPLE_FUR) { target.body.ChangeMainFur(targetFur); } else { target.UpdateBody(BodyType.SIMPLE_FUR, targetFur); } if (!oldData.IsFurBodyType()) { sb.Append(ChangedBodyText(target, oldData)); } else { sb.Append(ChandedFurToSpots(target, oldData)); } if (++totalChanges >= changeCount) { return(FinalizeTransformation(target, sb, totalChanges)); } } //if isEnhanced to probova give a shitty cow face else if (isEnhanced && target.face.type != FaceType.COW_MINOTAUR) { var oldData = target.face.AsReadOnlyData(); target.UpdateFace(FaceType.COW_MINOTAUR); sb.Append(ChangedFaceText(target, oldData)); if (++totalChanges >= changeCount) { return(FinalizeTransformation(target, sb, totalChanges)); } } //Give the player bovine horns, or increase their size, same as the minotaur //New horns or expanding mino horns if (!isPurified && Utils.Rand(3) == 0) { var oldHorns = target.horns.AsReadOnlyData(); if (target.horns.type != HornType.BOVINE) { target.UpdateHorns(HornType.BOVINE); sb.Append(ChangedHornsText(target, oldHorns)); if (++totalChanges >= changeCount) { return(FinalizeTransformation(target, sb, totalChanges)); } } else if (target.horns.type == HornType.BOVINE && target.horns.CanStrengthen && target.horns.significantHornSize < 5) { target.horns.StrengthenTransform(); sb.Append(MadeHornsBigger(target, oldHorns)); if (++totalChanges >= changeCount) { return(FinalizeTransformation(target, sb, totalChanges)); } } } //Increase the size of the player's hips, if they are not already childbearing or larger if (Utils.Rand(2) == 0 && target.hips.size < 15) { if (isPurified && target.hips.size < 8 || !isPurified) { var oldHips = target.hips.AsReadOnlyData(); if (target.build.GrowHips((byte)(1 + Utils.Rand(4))) > 0) { sb.Append(WidenedHipsText(target, oldHips)); if (++totalChanges >= changeCount) { return(FinalizeTransformation(target, sb, totalChanges)); } } } } // Remove gills if (Utils.Rand(4) == 0 && target.gills.type != GillType.NONE) { var oldData = target.gills.AsReadOnlyData(); target.RestoreGills(); sb.Append(RestoredGillsText(target, oldData)); if (++totalChanges >= changeCount) { return(FinalizeTransformation(target, sb, totalChanges)); } } //Increase the size of the player's ass (less likely then hips), if it is not already somewhat big if (Utils.Rand(2) == 0 && target.butt.size < 8 || (!isPurified && target.butt.size < 13)) { var oldButt = target.butt.AsReadOnlyData(); if (target.butt.GrowButt((byte)(1 + Utils.Rand(2))) > 0) { sb.Append(GrewButtText(target, oldButt)); if (++totalChanges >= changeCount) { return(FinalizeTransformation(target, sb, totalChanges)); } } } //Nipples Turn Back: if (target.genitals.hasBlackNipples && Utils.Rand(3) == 0) { target.genitals.SetBlackNipples(false); sb.Append(RemovedBlackNippleText(target)); if (++totalChanges >= changeCount) { return(FinalizeTransformation(target, sb, totalChanges)); } } //Debugcunt if (target.hasVagina && target.vaginas.Any(x => x.type != VaginaType.defaultValue) && Utils.Rand(3) == 0) { var oldCollection = target.genitals.allVaginas.AsReadOnlyData(); target.vaginas.ForEach(x => target.genitals.RestoreVagina(x)); sb.Append(RestoreAllVaginasText(target, oldCollection)); if (++totalChanges >= changeCount) { return(FinalizeTransformation(target, sb, totalChanges)); } } //this is the fallthrough that occurs when a tf item goes through all the changes, but does not proc enough of them to exit early. it will apply however many changes //occurred, then return the contents of the stringbuilder. return(FinalizeTransformation(target, sb, changeCount - totalChanges)); }
protected internal override string DoTransformation(Creature target, out bool isBadEnd) { isBadEnd = false; //by default, this is 2 rolls at 50%, so a 25% chance of 0 additional tfs, 50% chance of 1 additional tf, 25% chance of 2 additional tfs. //also takes into consideration any perks that increase or decrease tf effectiveness. if you need to roll out your own, feel free to do so. int changeCount = GenerateChangeCount(target, new int[] { 2, 3, 3 }); int remainingChanges = changeCount; StringBuilder sb = new StringBuilder(); //For all of these, any text regarding the transformation should be instead abstracted out as an abstract string function. append the result of this abstract function //to the string builder declared above (aka sb.Append(FunctionCall(variables));) string builder is just a fancy way of telling the compiler that you'll be creating a //long string, piece by piece, so don't do any crazy optimizations first. //the initial text for starting the transformation. feel free to add additional variables to this if needed. sb.Append(InitialTransformationText(target)); //Add any free changes here - these can occur even if the change count is 0. these include things such as change in stats (intelligence, etc) //change in height, hips, and/or butt, or other similar stats. //this will handle the edge case where the change count starts out as 0. if (remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } //Any transformation related changes go here. these typically cost 1 change. these can be anything from body parts to gender (which technically also changes body parts, //but w/e). You are required to make sure you return as soon as you've applied changeCount changes, but a single line of code can be applied at the end of a change to do //this for you. //paste this line after any tf is applied, and it will: automatically decrement the remaining changes count. if it becomes 0 or less, apply the total number of changes //underwent to the target's change count (if applicable) and then return the StringBuilder content. //if (--remainingChanges <= 0) return ApplyChangesAndReturn(target, sb, changeCount - remainingChanges); //Speed Increase: if (target.relativeSpeed < 100 && Utils.Rand(3) == 0) { target.ChangeSpeed(1); } //Strength Loss: else if (target.relativeStrength > 40 && Utils.Rand(3) == 0) { target.ChangeStrength(-1); } //Sensitivity Increase: if (target.relativeSensitivity < 70 && target.hasCock && Utils.Rand(3) == 0) { target.ChangeSensitivity(5); } //Libido Increase: if (target.relativeLibido < 70 && target.hasVagina && Utils.Rand(3) == 0) { target.ChangeLibido(2); if (target.relativeLibido < 30) { target.ChangeLibido(2); } } //Body Mass Loss: if (target.build.thickness > 40 && Utils.Rand(3) == 0) { target.build.ChangeThicknessToward(40, 3); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //Thigh Loss: (towards \"girly\") if (target.hips.size >= 10 && Utils.Rand(4) == 0) { target.hips.ShrinkHips(); if (target.hips.size > 15) { target.hips.ShrinkHips((byte)(2 + Utils.Rand(3))); } if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //Thigh Gain: (towards \"girly\") if (target.hips.size < 6 && Utils.Rand(4) == 0) { target.hips.GrowHips(); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //Breast Loss: (towards A cup) CupSize largestSize = target.genitals.BiggestCupSize(); CupSize targetCup = EnumHelper.Max(target.genitals.smallestPossibleCupSize, CupSize.A); //Mod note: both shrink and gain combined into one check. if (largestSize != targetCup && Utils.Rand(4) == 0) { foreach (Breasts breast in target.breasts) { //Mod Note: Generally i prefer the enum value over magic constants, but i have no idea what 70 is in cup land and don't want to look it up. if (breast.cupSize > (CupSize)70) { breast.ShrinkBreasts((byte)(Utils.Rand(3) + 15)); } else if (breast.cupSize > (CupSize)50) { breast.ShrinkBreasts((byte)(Utils.Rand(3) + 10)); } else if (breast.cupSize > (CupSize)30) { breast.ShrinkBreasts((byte)(Utils.Rand(3) + 7)); } else if (breast.cupSize > (CupSize)15) { breast.ShrinkBreasts((byte)(Utils.Rand(3) + 4)); } else if (breast.cupSize > targetCup) { breast.ShrinkBreasts((byte)(2 + Utils.Rand(2))); } //Mod note: if we shrunk it below the target cup size or it already was, if (breast.cupSize < targetCup) { breast.SetCupSize(targetCup); } } if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //Penis Reduction towards 3.5 Inches: if (target.genitals.LongestCockLength() >= 3.5 && target.hasCock && Utils.Rand(2) == 0) { if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //Testicle Reduction: if (target.balls.count > 0 && target.hasCock && (target.balls.size > 1 || target.balls.count > 1) && Utils.Rand(4) == 0) { if (target.balls.size > 20) { target.balls.ShrinkBalls(6); } else if (target.balls.size > 15) { target.balls.ShrinkBalls(5); } else if (target.balls.size > 12) { target.balls.ShrinkBalls(4); } else if (target.balls.size > 10) { target.balls.ShrinkBalls(3); } else if (target.balls.size > 8) { target.balls.ShrinkBalls(2); } else if (target.balls.size > 1) { target.balls.ShrinkBalls(1); } else { target.balls.MakeUniBall(); } if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //Anal Wetness Increase: if (target.ass.wetness < AnalWetness.SLIME_DROOLING && Utils.Rand(4) == 0) { //Anal Wetness Increase Final (always loose): target.ass.IncreaseWetness(); //buttChange(30,false,false,false); if (target.ass.looseness < AnalLooseness.STRETCHED) { target.ass.IncreaseLooseness(); } if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } target.ChangeSensitivity(2); } //Fertility Decrease: if (target.hasVagina && Utils.Rand(4) == 0) { target.ChangeSensitivity(-2); target.fertility.DecreaseFertility((byte)(1 + Utils.Rand(3))); if (target.fertility.currentFertility < 4) { target.fertility.SetFertility(4); } if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //Male Effects if (target.gender == Gender.MALE) { //Femininity Increase Final (max femininity allowed increased by +10): if (Utils.Rand(4) == 0) { if (target.femininity < 70 && target.femininity >= 60) { if (target.femininity.femininityLimitedByGender) { target.femininity.ActivateAndrogyny(); } target.femininity.IncreaseFemininity(10); if (target.femininity > 70) { target.femininity.SetFemininity(70); } if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //Femininity Increase: else { target.femininity.IncreaseFemininity(10); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } } //Muscle tone reduction: if (target.build.muscleTone > 20 && Utils.Rand(4) == 0) { target.build.DecreaseMuscleTone(10); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } } //Female Effects else if (target.gender == Gender.FEMALE) { //Masculinity Increase: if (target.femininity > 30 && Utils.Rand(4) == 0) { target.femininity.IncreaseMasculinity(10); if (target.femininity < 30) { target.femininity.SetFemininity(30); //Masculinity Increase Final (max masculinity allowed increased by +10): if (target.femininity.femininityLimitedByGender) { target.femininity.ActivateAndrogyny(); } } if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //Muscle tone gain: if (target.build.muscleTone < 80 && Utils.Rand(4) == 0) { target.build.GainMuscle(10); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } } //Neck restore if (target.neck.type != NeckType.HUMANOID && Utils.Rand(4) == 0) { NeckData oldData = target.neck.AsReadOnlyData(); target.RestoreNeck(); sb.Append(RestoredNeckText(target, oldData)); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //Rear body restore if (!target.back.isDefault && Utils.Rand(5) == 0) { BackData oldData = target.back.AsReadOnlyData(); target.RestoreBack(); sb.Append(RestoredBackText(target, oldData)); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //Ovi perk loss if (target.womb.canRemoveOviposition && Utils.Rand(5) == 0) { target.womb.ClearOviposition(); sb.Append(ClearOvipositionText(target)); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //Nipples Turn Black: if (!target.genitals.hasBlackNipples && Utils.Rand(6) == 0) { target.genitals.SetBlackNipples(true); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //Remove odd eyes if (target.eyes.count != 2 && target.eyes.type != EyeType.SAND_TRAP && Utils.Rand(2) == 0) { EyeData oldData = target.eyes.AsReadOnlyData(); target.RestoreEyes(); sb.Append(RestoredEyesText(target, oldData)); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //PC Trap Effects if (target.eyes.type != EyeType.SAND_TRAP && Utils.Rand(4) == 0) { //Eyes Turn Black: EyeData oldData = target.eyes.AsReadOnlyData(); target.UpdateEyes(EyeType.SAND_TRAP); sb.Append(UpdateEyesText(target, oldData)); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //V****a Turns Black: //has a v****a and any v****a is not a sand trap (aka, not all of the vaginas are sand trap vags) if (target.hasVagina && !target.genitals.OnlyHasVaginasOfType(VaginaType.SAND_TRAP) && Utils.Rand(4) == 0) { //(Wet: //(Corruption <50: target.DeltaCreatureStats(sens: 2, lus: 10); target.vaginas.ForEach(x => target.genitals.UpdateVagina(x, VaginaType.SAND_TRAP)); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //Dragonfly Wings: if (target.wings.type != WingType.DRAGONFLY && Utils.Rand(4) == 0) { //Wings Fall Out: You feel a sharp pinching sensation in your shoulders and you cringe slightly. Your former dragonfly wings make soft, papery sounds as they fall into the dirt behind you. if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } target.UpdateWings(WingType.DRAGONFLY); } if (remainingChanges == changeCount) { } //this is the fallthrough that occurs when a tf item goes through all the changes, but does not proc enough of them to exit early. it will apply however many changes //occurred, then return the contents of the stringbuilder. return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); }
public Espresso(CupSize size) : base(size) { }
public Coffee(string strSize) { CupSize Size = FromStringToSize(strSize); Price = FromSizeToPrice(Size); }
protected internal override string DoTransformation(Creature target, out bool isBadEnd) { isBadEnd = false; //for some unknown reason, demon tfs roll out their own chance system completely unique to them. ok. StringBuilder sb = new StringBuilder(); //For all of these, any text regarding the transformation should be instead abstracted out as an abstract string function. append the result of this abstract function //to the string builder declared above (aka sb.Append(FunctionCall(variables));) string builder is just a fancy way of telling the compiler that you'll be creating a //long string, piece by piece, so don't do any crazy optimizations first. //the initial text for starting the transformation. feel free to add additional variables to this if needed. sb.Append(InitialTransformationText(target)); //Add any free changes here - these can occur even if the change count is 0. these include things such as change in stats (intelligence, etc) //change in height, hips, and/or butt, or other similar stats. int rando = Utils.Rand(100); int delta = target.GetExtraData()?.deltaTransforms ?? 0; if (delta != 0) { rando += 5 * delta + Utils.Rand(5 * delta); } //First, check if this tf has the male flag set (for male or herm tfs). If it does, add or grow cocks. if (desiredGender.HasFlag(Gender.MALE)) { byte addedCocks = 0; //if our initial roll was a crit, roll again. if we crit again, we may add several cocks, if possible. if (rando >= 85 && target.cocks.Count < Genitals.MAX_COCKS && Utils.Rand(10) < target.corruptionTrue / 25) { addedCocks = GrowCockGeneric(target, (byte)(Utils.Rand(2) + 2)); target.DeltaCreatureStats(lib: 3 * addedCocks, sens: 5 * addedCocks, lus: 10 * addedCocks); if (!isPurified) { target.IncreaseCorruption(8); } } //otherwise, only add a c**k if we have none or we originally rolled a crit (but failed to crit again) else if (target.cocks.Count == 0 || (rando >= 85 && target.cocks.Count < Genitals.MAX_COCKS)) { addedCocks = GrowCockGeneric(target, 1); target.DeltaCreatureStats(lib: 3, sens: 5, lus: 10); if (!isPurified) { target.IncreaseCorruption(5); } } //if that fails, it means we had a c**k already, or can't grow any more of them. else { C**k shortest = target.genitals.ShortestCock(); double lengthDelta; if (rando >= 45) { lengthDelta = shortest.IncreaseLength(Utils.Rand(3) + 3); shortest.IncreaseThickness(1); } else if (Utils.Rand(4) == 0) { lengthDelta = shortest.IncreaseLength(3); } else { lengthDelta = shortest.IncreaseLength(1); } target.DeltaCreatureStats(lib: 2, sens: 1, lus: 5 + lengthDelta * 3); if (!isPurified) { target.IncreaseCorruption(); } //no idea why this occurs, but ok. target.IncreaseIntelligence(1); } } //Otherwise, we're targeting female demon tfs only. this means we need to shrink (and possibly remove) the largest c**k the target has, unless hyper happy is on. else if (!hyperHappy && target.hasCock) { C**k largest = target.genitals.LongestCock(); //this loops through all the cocks and finds the longest. obviously, if the count is 1, this is simply the first element. //we'll need this if it gets removed. if not, this can still be used, this time to determine how much we shrunk. CockData oldData = largest.AsReadOnlyData(); //try decreasing it by 1-3. if this causes it to be removed instead, that's fine, but we need to know. //Note that this remove is now IN PLACE, not LAST. so if we remove the 3rd one, the old 4th is now 3rd, and so on. bool removed = target.genitals.ShrinkCockAndRemoveIfTooSmall(largest, Utils.Rand(3) + 1); } //Then, check if the tf has the female flag set (for female or herm tfs). if it does, add a v****a (if needed), and increase breast size. if (desiredGender.HasFlag(Gender.FEMALE)) { //don't currently have a v****a and herm tf or we're genderless, or it's a crit, or we rerolled a crit. if (!target.hasVagina && (desiredGender == Gender.HERM || target.gender == Gender.GENDERLESS || rando > 65 || Utils.Rand(3) == 0)) { target.genitals.AddVagina(VaginaType.HUMAN); } //do have one, and rolled a high crit. else if (target.hasVagina && rando >= 85) { foreach (V****a vag in target.vaginas) { //grow each c**t anywhere from 0.25in to 1in, if they are below the largest normal size. if (vag.c**t.length < vag.c**t.largestNormalSize) { vag.GrowClit((Utils.Rand(4) + 1) * 0.25); //cap it at the largest normal size. if (vag.c**t.length > vag.c**t.largestNormalSize) { vag.SetClitSize(vag.c**t.largestNormalSize); } } } } //do have one, rolled a crit, but not a high crit. else if (target.hasVagina && rando > 65) { target.HaveGenericVaginalOrgasm(0, true, true); target.vaginas.ForEach(x => x.IncreaseWetness()); } //now, breasts. these are the fallback, of sorts, so they grow larger when we don't crit. they also grow larger when we crit if we're targeting herms. if (rando < 85 || desiredGender == Gender.HERM) { //only occurs via herm. if (rando >= 85) { target.breasts.ForEach(x => x.GrowBreasts(3)); } else { byte temp = (byte)(1 + Utils.Rand(3)); CupSize largestSize = target.genitals.BiggestCupSize(); if (largestSize < CupSize.B && Utils.Rand(3) == 0) { temp++; } if (largestSize < CupSize.DD && Utils.Rand(4) == 0) { temp++; } if (largestSize < CupSize.DD_BIG && Utils.Rand(5) == 0) { temp++; } target.breasts.ForEach(x => x.GrowBreasts(temp)); } } } //if not, we're targeting male demon tfs only. this means we may need to shrink any overlarge breasts. Additionally, higher rng rolls may now remove vaginas. else if (!hyperHappy) { //if high crit: decrease bonus capacity, and remove a v****a, flat-out. if (rando >= 85 && target.hasVagina) { target.genitals.DecreaseBonusVaginalCapacity(5); target.genitals.RemoveVagina(); } //otherwise, if somewhat high, decrease bonus vaginal capacity (all vaginas), and wetness (last v****a). if this causes the bonus capacity to drop to 0 //and would cause it to go negative if we allowed that, remove the last v****a. else if (rando >= 65) { V****a lastVagina = target.vaginas[target.vaginas.Count - 1]; lastVagina.DecreaseWetness(1); //this is being super pedantic, but i'd prefer it lower the stat, then remove the v****a. hence this bool here. bool remove = target.genitals.standardBonusVaginalCapacity < 5; //decrease first. target.genitals.DecreaseBonusVaginalCapacity(5); //then remove it. if (remove) { target.genitals.RemoveVagina(); } } // if (target.genitals.BiggestCupSize() > target.genitals.smallestPossibleCupSize && (rando >= 85 || (rando > 65 && Utils.RandBool()) || (rando <= 65 && Utils.Rand(4) == 0))) { foreach (Breasts breast in target.breasts) { if (breast.cupSize > target.genitals.smallestPossibleCupSize) { byte amount = 1; if (rando >= 85) { amount++; } breast.ShrinkBreasts(amount); } } } } //never called in vanilla. if i read it correctly, it just initializes to 0 with a max of 1. int changeCount = base.GenerateChangeCount(target, new int[] { 3 }, 0, 0); if (changeCount == 0) { return(ApplyChangesAndReturn(target, sb, 0)); } int remainingChanges = changeCount; //Neck restore if (!target.neck.isDefault && Utils.Rand(4) == 0) { NeckData oldData = target.neck.AsReadOnlyData(); target.RestoreNeck(); sb.Append(RestoredNeckText(target, oldData)); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //Rear body restore if (!target.back.isDefault && Utils.Rand(5) == 0) { BackData oldData = target.back.AsReadOnlyData(); target.RestoreBack(); sb.Append(RestoredBackText(target, oldData)); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //Ovi perk loss if (target.womb.canRemoveOviposition && Utils.Rand(5) == 0) { target.womb.ClearOviposition(); sb.Append(ClearOvipositionText(target)); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //Demonic changes - higher chance with higher corruption. if (Utils.Rand(40) + target.corruption / 3 > 35 && !isPurified) { //Change tail if already horned. if (target.tail.type != TailType.DEMONIC && !target.horns.isDefault) { target.IncreaseCorruption(4); TailData oldData = target.tail.AsReadOnlyData(); target.UpdateTail(TailType.DEMONIC); sb.Append(UpdateTailText(target, oldData)); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //grow horns! if (target.horns.numHorns == 0 || (Utils.Rand(target.horns.numHorns + 3) == 0)) { if (target.horns.numHorns < 12 && (target.horns.type == HornType.NONE || target.horns.type == HornType.DEMON)) { if (target.horns.type == HornType.NONE) { target.UpdateHorns(HornType.DEMON); } target.IncreaseCorruption(3); } //Text for shifting horns else if (target.horns.type != HornType.DEMON) { target.UpdateHorns(HornType.DEMON); target.IncreaseCorruption(3); } if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //Nipples Turn Back: if (target.genitals.hasBlackNipples && Utils.Rand(3) == 0) { target.genitals.SetBlackNipples(false); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //remove fur if (target.face.type != FaceType.HUMAN || (target.body.type != BodyType.HUMANOID && Utils.Rand(3) == 0)) { //Remove face before fur! if (target.face.type != FaceType.HUMAN) { target.RestoreFace(); } //De-fur else if (target.body.type != BodyType.HUMANOID) { target.RestoreBody(); } if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //Demon tongue if (target.tongue.type == TongueType.SNAKE && Utils.Rand(3) == 0) { TongueData oldData = target.tongue.AsReadOnlyData(); target.UpdateTongue(TongueType.DEMONIC); sb.Append(UpdateTongueText(target, oldData)); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //foot changes - requires furless if (target.body.type == BodyType.HUMANOID && Utils.Rand(4) == 0) { bool changed; //Males/genderless get clawed feet if (!target.gender.HasFlag(Gender.FEMALE) || (target.gender == Gender.HERM && target.genitals.AppearsMoreMaleThanFemale())) { changed = target.UpdateLowerBody(LowerBodyType.DEMONIC_CLAWS); } //Females/futa get high heels else { changed = target.UpdateLowerBody(LowerBodyType.DEMONIC_HIGH_HEELS); } if (changed && --remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } //Grow demon wings if ((target.wings.type != WingType.BAT_LIKE || !target.wings.isLarge || target.back.type == BackType.SHARK_FIN) && Utils.Rand(8) == 0 && target.IsCorruptEnough(50)) { //grow smalls to large if (target.wings.type == WingType.BAT_LIKE && target.IsCorruptEnough(75)) { target.wings.GrowLarge(); } else { target.UpdateWings(WingType.BAT_LIKE); } if (target.back.type == BackType.SHARK_FIN) { target.RestoreBack(); } if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); } } } //this is the fallthrough that occurs when a tf item goes through all the changes, but does not proc enough of them to exit early. it will apply however many changes //occurred, then return the contents of the stringbuilder. return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges)); }
private void MinMaleCupChanged(CupSize oldValue) { source.genitals.perkData.ValidateCupSize(); }
public Beverage(CupSize size) { this.size = size; }
public HouseBlend(CupSize cupSize) : this() { SetSize(cupSize); }
protected internal override string DoTransformation(Creature target, out bool isBadEnd) { isBadEnd = false; int changeLimit = GenerateChangeCount(target, new int[] { 2, 2 }); int remainingChanges = changeLimit; //crit is our modifier for basically all stats. 1 is default, though any non-standard will proc the non-default //standard also has a 15% chance of proccing it too. int crit = 1; if (modifiers > CanineModifiers.STANDARD || Utils.Rand(20) < 3) { crit = Utils.Rand(20) / 10 + 2; } bool hasCrit() => crit > 1; StringBuilder sb = new StringBuilder(); bool DoKnotChanges(double delta) { if (target.hasCock) { bool changed = false; int dogCockCount = target.genitals.CountCocksOfType(CockType.DOG); if (dogCockCount > 0) { C**k smallestKnot = target.cocks.MinItem(x => x.type == CockType.DOG ? (double?)x.knotMultiplier : null); if (smallestKnot.knotMultiplier > 2) { delta /= 10; } else if (smallestKnot.knotMultiplier > 1.75) { delta /= 5; } else if (smallestKnot.knotMultiplier > 1.5) { delta /= 2; } double knotMultiplierDelta = smallestKnot.IncreaseKnotMultiplier(delta); if (knotMultiplierDelta != 0) { sb.Append(EnlargedSmallestKnotText(target, target.cocks.IndexOf(smallestKnot), knotMultiplierDelta, dogCockCount > 1)); changed = true; } } target.DeltaCreatureStats(sens: 0.5, lus: 5 * crit); return(changed); } return(false); } sb.Append(InitialTransformationText(modifiers, hasCrit())); //bad end related checks if (hasCrit() && target.body.hasActiveFurData && target.face.type == FaceType.DOG && target.ears.type == EarType.DOG && target.lowerBody.type == LowerBodyType.DOG && target.tail.type == TailType.DOG && target is IExtendedCreature extended) { //can get bad end. if (extended.extendedData.hasDoggoWarning && !extended.extendedData.resistsTFBadEnds) { //bad end. if (Utils.RandBool()) { sb.Append(BadEndText(target)); isBadEnd = true; return(ApplyChangesAndReturn(target, sb, 0)); } //get lucky, but warn that they got lucky else { sb.Append(DoggoWarningText(target, true)); } } //not warned else if (!extended.extendedData.hasDoggoWarning) { //warn extended.extendedData.hasDoggoWarning = true; sb.Append(DoggoWarningText(target, false)); } } //stat changes if (modifiers.HasFlag(CanineModifiers.BLACK)) { target.IncreaseCreatureStats(lus: (byte)(5 + Utils.Rand(5)), lib: (byte)(2 + Utils.Rand(4)), corr: (byte)(2 + Utils.Rand(4))); } //stat changes (cont.) double strengthIncrease = 0; double speedIncrease = 0; double intelligenceDecrease = 0; if (target.relativeStrength < 50 && Utils.Rand(3) == 0) { strengthIncrease = target.IncreaseStrength(crit); } if (target.relativeSpeed < 30 && Utils.Rand(3) == 0) { speedIncrease = target.IncreaseSpeed(crit); } if (target.relativeIntelligence > 30 && Utils.Rand(3) == 0) { intelligenceDecrease = target.DecreaseIntelligence(crit); } sb.Append(StatChangeText(target, strengthIncrease, speedIncrease, intelligenceDecrease)); //modifier effects (no cost) //double pepper if (modifiers.HasFlag(CanineModifiers.DOUBLE)) { int dogCocks = target.genitals.CountCocksOfType(CockType.DOG); //already has 2+ dog cocks. if (dogCocks >= 2) { //just treat it like a large. so we'll just bitwise or the //large flag in. modifiers |= CanineModifiers.LARGE; } //has no dog cocks. else if (dogCocks == 0) { //has no cocks. - grow 2 if (target.cocks.Count == 0) { target.AddCock(CockType.DOG, 7 + Utils.Rand(7), 1.5 + Utils.Rand(10) / 10, 1.7); target.AddCock(CockType.DOG, 7 + Utils.Rand(7), 1.5 + Utils.Rand(10) / 10, 1.7); sb.Append(GrewTwoDogCocksHadNone(target)); } //has one c**k. - grow one, change one else if (target.cocks.Count == 1) { CockData oldCockData = target.cocks[0].AsReadOnlyData(); target.genitals.UpdateCockWithKnot(0, CockType.DOG, 1.5); if (target.cocks[0].length < 10) { target.cocks[0].SetLength(10); } target.AddCock(CockType.DOG, 7 + Utils.Rand(7), 1.5 + Utils.Rand(10) / 10.0, 1.7); sb.Append(ConvertedFirstDogCockGrewSecond(target, oldCockData)); } //has 2+ cocks. -change 2 else { CockData firstOldData = target.cocks[0].AsReadOnlyData(); CockData secondOldData = target.cocks[1].AsReadOnlyData(); target.genitals.UpdateCockWithKnot(0, CockType.DOG, 1.5); if (target.cocks[0].length < 10) { target.cocks[0].SetLength(10); } target.genitals.UpdateCockWithKnot(1, CockType.DOG, 1.5); if (target.cocks[1].length < 10) { target.cocks[1].SetLength(10); } sb.Append(ConvertedTwoCocksToDog(target, firstOldData, secondOldData)); } } //one dog c**k. else { if (target.cocks.Count == 1) { target.AddCock(CockType.DOG, 7 + Utils.Rand(7), 1.5 + Utils.Rand(10) / 10.0, 1.7); sb.Append(GrewSecondDogCockHadOne(target)); } else { if (target.cocks[0].type == CockType.DOG) { CockData oldData = target.cocks[1].AsReadOnlyData(); target.genitals.UpdateCockWithKnot(1, CockType.DOG, 1.5); if (target.cocks[1].length < 10) { target.cocks[1].SetLength(10); } sb.Append(ConvertedOneCockToDogHadOne(target, 1, oldData)); } else { CockData oldData = target.cocks[0].AsReadOnlyData(); target.genitals.UpdateCockWithKnot(0, CockType.DOG, 1.5); if (target.cocks[0].length < 10) { target.cocks[0].SetLength(10); } sb.Append(ConvertedOneCockToDogHadOne(target, 0, oldData)); } } } target.IncreaseCreatureStats(lib: 2, lus: 50); } //there are two ways to proc this - either via a knotty modifier (written here), or via random chance and/or with a large pepper (written later) //however, a knotty pepper modifier has no tf cost, the other check does. also, this will modify a c**k if none have a dog knot, the other will not. if (modifiers.HasFlag(CanineModifiers.KNOTTY)) { double delta = ((Utils.Rand(2) + 5) / 20) * crit; if (!DoKnotChanges(delta)) { if (target.hasCock) { CockData oldCockData = target.cocks[0].AsReadOnlyData(); double knotSize = 1.75; if (target.cocks[0].hasKnot) { knotSize = Math.Max(2.1, target.cocks[0].knotMultiplier); } target.genitals.UpdateCockWithKnot(0, CockType.DOG, knotSize); if (target.cocks[0].length < 10) { target.cocks[0].SetLength(10); } sb.Append(ConvertedOneCockToDog(target, 0, oldCockData)); } else { sb.Append(WastedKnottyText(target)); } } } //bulby if (modifiers.HasFlag(CanineModifiers.BULBY)) { if (!target.hasBalls) { target.genitals.GrowBalls(2, 1); target.DeltaCreatureStats(lib: 2, lus: -10); sb.Append(GrewBallsText(target)); } else if (target.balls.uniBall) { BallsData oldData = target.balls.AsReadOnlyData(); target.genitals.ConvertToNormalBalls(); target.DeltaCreatureStats(lib: 1, lus: 1); sb.Append(EnlargedBallsText(target, oldData)); } else { BallsData oldData = target.balls.AsReadOnlyData(); byte enlargeAmount = target.genitals.balls.EnlargeBalls(1); target.IncreaseCreatureStats(lib: 1, lus: 3); sb.Append(EnlargedBallsText(target, oldData)); } } if (remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeLimit - remainingChanges)); } //tfs (cost 1). //restore neck if (target.neck.type != NeckType.defaultValue && Utils.Rand(4) == 0) { NeckData oldNeck = target.neck.AsReadOnlyData(); target.RestoreNeck(); sb.Append(RestoredNeckText(target, oldNeck)); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeLimit - remainingChanges)); } } //remove oviposition if (target.womb.canRemoveOviposition && Utils.Rand(5) == 0) { if (target.womb.ClearOviposition()) { sb.Append(RemovedOvipositionText(target)); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeLimit - remainingChanges)); } } } //remove feather-hair if (RemoveFeatheryHair(target)) { sb.Append(RemovedFeatheryHairText(target)); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeLimit - remainingChanges)); } } //knot multiplier (but not knotty) if (!modifiers.HasFlag(CanineModifiers.KNOTTY) && target.genitals.CountCocksOfType(CockType.DOG) > 0 && (modifiers.HasFlag(CanineModifiers.LARGE) || Utils.Rand(7) < 5)) { double delta = ((Utils.Rand(2) + 1) / 20.0) * crit; if (DoKnotChanges(delta)) { if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeLimit - remainingChanges)); } } } //transform a c**k. if (target.genitals.CountCocksOfType(CockType.DOG) < target.cocks.Count && (modifiers.HasFlag(CanineModifiers.LARGE) || Utils.Rand(8) < 5)) { C**k nonDoggo = target.cocks.FirstOrDefault(x => x.type != CockType.DOG && x.type != CockType.DEMON); //find any c**k that isn't a dog, but also isn't a demon c**k. if (nonDoggo != null) { CockData oldData = nonDoggo.AsReadOnlyData(); int index = target.cocks.IndexOf(nonDoggo); target.genitals.UpdateCock(index, CockType.DOG); sb.Append(ConvertedOneCockToDog(target, index, oldData)); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeLimit - remainingChanges)); } } else { C**k demonSpecialCase = target.cocks.FirstOrDefault(x => x.type == CockType.DEMON); int index = demonSpecialCase.cockIndex; if (demonSpecialCase != null) { double delta = demonSpecialCase.IncreaseThickness(2); if (delta != 0) { sb.Append(CouldntConvertDemonCockThickenedInstead(target, index, delta)); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeLimit - remainingChanges)); } } } } } //update cum. now, if it reaches the cap, it simply uses the new flat amount adder (up to a certain point). it does not use the messy o****m perk //anymore because i've tried to remove calls to random perks because it's not very future-proof - what happens when a new perk is added that has a //similar effect? do we add that check literally everywhere too? (of course, if a perk is unique enough that nothing else will act in the same way, //that's fine. i dunno, it's difficult to try and clean everything up without being able to predict the future, which is admittedly impossible) if (target.hasCock && (target.genitals.cumMultiplier < 1.5 || target.genitals.additionalCum < 500) && Utils.RandBool()) { double delta; bool wasMultiplier; if (target.genitals.cumMultiplier < 1.5) { delta = target.genitals.IncreaseCumMultiplier(0.05 * crit); wasMultiplier = true; } else { delta = target.genitals.AddFlatCumAmount(50); wasMultiplier = false; } sb.Append(AddedCumText(target, delta, wasMultiplier)); } if (target.hasCock && modifiers.HasFlag(CanineModifiers.LARGE)) { C**k smallest = target.genitals.ShortestCock(); CockData oldData = smallest.AsReadOnlyData(); smallest.IncreaseLength(Utils.Rand(4) + 3); if (smallest.girth < 1) { double delta = 1 - smallest.girth; smallest.IncreaseThickness(delta); } sb.Append(GrewSmallestCockText(target, smallest.cockIndex, oldData)); } //do female changes. //if we have a vag and > flat breasts. if (target.hasVagina && target.genitals.BiggestCupSize() > CupSize.FLAT) { byte breastCount = (byte)target.breasts.Count; if (breastCount < 3) { BreastCollectionData oldBreastData = target.genitals.allBreasts.AsReadOnlyData(); //in vanilla code, we had some strange checks here that required the first row (and only the first row) be a certain size. //now, we check all the rows, but no longer require any of them to be a certain size. instead, if it's not the right size, we make it that size, //then add the row. so, for two rows, your first row must be at least a B-Cup. for 3: first must be a C cup, second an A cup. //if we supported 4 rows, it'd be D, B, A. for (int x = 0; x < target.breasts.Count; x++) { CupSize requiredSize = (CupSize)(byte)(target.breasts.Count - x); if (x == 0) { requiredSize++; } if (target.breasts[x].cupSize < requiredSize) { target.breasts[x].SetCupSize(requiredSize); } } target.genitals.AddBreastRow(target.breasts[breastCount - 1].cupSize.ByteEnumSubtract(1)); bool doCrit = false, uberCrit = false; if (target.breasts.Count == 2) { target.IncreaseCreatureStats(lus: 5, sens: 6); } else if (hasCrit()) { doCrit = true; if (crit > 2) { target.IncreaseCreatureStats(sens: 6, lus: 15); uberCrit = true; } else { target.IncreaseCreatureStats(sens: 3, lus: 10); } } sb.Append(UpdateAndGrowAdditionalRowText(target, oldBreastData, doCrit, uberCrit)); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeLimit - remainingChanges)); } } else { BreastCollectionData oldBreastData = target.genitals.allBreasts.AsReadOnlyData(); //only call the normalize text if we actually did anything. related, anthro breasts now returns a bool. thanks, fox tfs. if (target.genitals.AnthropomorphizeBreasts()) { sb.Append(NormalizedBreastSizeText(target, oldBreastData)); } } } //Go into heat if (EnterHeat(target, out bool increased)) { sb.Append(EnterOrIncreaseHeatText(target, increased)); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeLimit - remainingChanges)); } } //doggo fantasies if (target.DogScore() > 3 && Utils.Rand(4) == 0) { sb.Append(DoggoFantasyText(target)); target.IncreaseLust(5 + (target.libidoTrue / 20)); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeLimit - remainingChanges)); } } //doggo tfs. if (!target.eyes.isDefault && Utils.Rand(5) == 0) { EyeData oldData = target.eyes.AsReadOnlyData(); target.RestoreEyes(); sb.Append(RestoredEyesText(target, oldData)); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeLimit - remainingChanges)); } } if (modifiers.HasFlag(CanineModifiers.BLACK) && !target.body.mainEpidermis.fur.IsIdenticalTo(HairFurColors.BLACK)) { //for now, we're ignoring underbody, apparently. if (target.body.type != BodyType.SIMPLE_FUR) //if (target.body.mainEpidermis.currentType != EpidermisType.FUR) { BodyData oldBodyData = target.body.AsReadOnlyData(); target.UpdateBody(BodyType.SIMPLE_FUR, new FurColor(HairFurColors.BLACK), FurTexture.THICK); sb.Append(ChangedBodyTypeText(target, oldBodyData)); } else { ReadOnlyFurColor oldFur = target.body.mainEpidermis.fur.AsReadOnly(); target.body.ChangeMainFur(new FurColor(HairFurColors.MIDNIGHT_BLACK), FurTexture.THICK); sb.Append(ChangedFurText(target, oldFur)); } if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeLimit - remainingChanges)); } } //again, we're ignoring underbody for now, idk. else if (target.lowerBody.type == LowerBodyType.DOG && target.tail.type == TailType.DOG && //target.body.mainEpidermis.currentType != EpidermisType.FUR target.body.type != BodyType.SIMPLE_FUR && Utils.Rand(4) == 0) { BodyData oldBodyData = target.body.AsReadOnlyData(); FurColor oldFur = target.body.mainEpidermis.fur; target.UpdateBody(BodyType.SIMPLE_FUR, Utils.RandomChoice(Species.DOG.availableColors)); sb.Append(ChangedBodyTypeText(target, oldBodyData)); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeLimit - remainingChanges)); } } if (target.lowerBody.type != LowerBodyType.DOG && target.tail.type == TailType.DOG && target.ears.type == EarType.DOG && Utils.Rand(3) == 0) { LowerBodyData oldData = target.lowerBody.AsReadOnlyData(); target.UpdateLowerBody(LowerBodyType.DOG); sb.Append(ChangedLowerBodyText(target, oldData)); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeLimit - remainingChanges)); } } if (target.ears.type != EarType.DOG && target.tail.type == TailType.DOG && Utils.RandBool()) { EarData oldData = target.ears.AsReadOnlyData(); target.UpdateEars(EarType.DOG); sb.Append(ChangedEarsText(target, oldData)); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeLimit - remainingChanges)); } } if (target.tail.type != TailType.DOG && Utils.Rand(3) == 0) { TailData oldData = target.tail.AsReadOnlyData(); target.UpdateTail(TailType.DOG); sb.Append(ChangedTailText(target, oldData)); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeLimit - remainingChanges)); } } if (target.arms.type != ArmType.DOG && target.body.isFurry && target.tail.type == TailType.DOG && target.lowerBody.type == LowerBodyType.DOG && Utils.Rand(4) == 0) { ArmData oldArmData = target.arms.AsReadOnlyData(); target.UpdateArms(ArmType.DOG); sb.Append(ChangedArmsText(target, oldArmData)); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeLimit - remainingChanges)); } } if (!target.gills.isDefault && Utils.Rand(4) == 0) { GillData oldGillData = target.gills.AsReadOnlyData(); target.RestoreGills(); sb.Append(RemovedGillsText(target, oldGillData)); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeLimit - remainingChanges)); } } if (target.body.isFurry && Utils.Rand(3) == 0) { target.DeltaCreatureStats(tou: 4, sens: -3); sb.Append(FallbackToughenUpText(target)); if (--remainingChanges <= 0) { return(ApplyChangesAndReturn(target, sb, changeLimit - remainingChanges)); } } if (target is CombatCreature cc2 && remainingChanges == changeLimit) { cc2.AddHP(20); sb.Append(NothingHappenedGainHpText(target)); target.IncreaseLust(3); } return(ApplyChangesAndReturn(target, sb, changeLimit - remainingChanges)); }