public VaginaCreator(VaginaType vaginaType, double?clitLengthInInches = null, VaginalWetness vaginalWetness = VaginalWetness.NORMAL,
                      VaginalLooseness vaginalLooseness = VaginalLooseness.TIGHT, bool omnibusClit           = false, bool isVirgin = true,
                      Dictionary <ClitPiercingLocation, PiercingJewelry> clitJewelry = null, Dictionary <LabiaPiercingLocation, PiercingJewelry> labiaJewelry = null)
 {
     type           = vaginaType;
     clitLength     = clitLengthInInches;
     wetness        = vaginalWetness;
     looseness      = vaginalLooseness;
     hasClitCock    = omnibusClit;
     clitPiercings  = clitJewelry == null ? null : new ReadOnlyDictionary <ClitPiercingLocation, PiercingJewelry>(clitJewelry);
     labiaPiercings = labiaJewelry == null ? null : new ReadOnlyDictionary <LabiaPiercingLocation, PiercingJewelry>(labiaJewelry);
     virgin         = isVirgin;
 }
Beispiel #2
0
        public static string AsAdjective(this VaginalWetness vaginalWetness)
        {
            switch (vaginalWetness)
            {
            case VaginalWetness.SLAVERING:
                return("absolutely drenched in fem-spunk");

            case VaginalWetness.DROOLING:
                return("dripping natural lubricant");

            case VaginalWetness.SLICK:
                return("slick with fem-spunk");

            case VaginalWetness.WET:
                return("wetter than normal");

            case VaginalWetness.DRY:
                return("rather dry");

            case VaginalWetness.NORMAL:
            default:
                return("only a little wet");
            }
        }
Beispiel #3
0
        public static string AsDescriptor(this VaginalWetness vaginalWetness)
        {
            switch (vaginalWetness)
            {
            case VaginalWetness.SLAVERING:
                return("slavering");

            case VaginalWetness.DROOLING:
                return("drooling");

            case VaginalWetness.SLICK:
                return("slick");

            case VaginalWetness.WET:
                return("wet");

            case VaginalWetness.DRY:
                return("dry");

            case VaginalWetness.NORMAL:
            default:
                return("");
            }
        }
Beispiel #4
0
        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));
        }
 private void CheckVaginalWetnessChanged(VaginalWetness oldValue)
 {
     source.genitals.perkData.ValidateVaginalWetness();
 }
Beispiel #6
0
        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, 4 });
            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);
#warning fix me
            int ngPlus(int value) => value;


            if (target.speed < ngPlus(100) && Utils.Rand(3) == 0)
            {
                //+3 spe if less than 50
                if (target.speed < ngPlus(50))
                {
                    target.ChangeSpeed(1);
                }
                //+2 spe if less than 75
                if (target.speed < ngPlus(75))
                {
                    target.ChangeSpeed(1);
                }
                //+1 if above 75.
                target.ChangeSpeed(1);
            }

            if (target.toughness > ngPlus(80) && Utils.Rand(4) == 0)
            {
                target.ChangeToughness(-1);
            }

            //-Reduces sensitivity.
            if (target.sensitivity > 20 && Utils.Rand(3) == 0)
            {
                target.ChangeSensitivity(-1);
            }

            //Raises libido greatly to 50, then somewhat to 75, then slowly to 100.
            if (target.libido < 100 && Utils.Rand(3) == 0)
            {
                //+3 lib if less than 50
                if (target.libido < 50)
                {
                    target.ChangeLibido(1);
                }
                //+2 lib if less than 75
                if (target.libido < 75)
                {
                    target.ChangeLibido(1);
                }
                //+1 if above 75.
                target.ChangeLibido(1);
            }

            //Sexual changes

            //-Lactation stoppage.
            if (target.genitals.isLactating && Utils.Rand(4) == 0)
            {
                if (target.HasPerk <Feeder>())
                {
                    target.RemovePerk <Feeder>();
                }

                target.genitals.SetLactationTo(LactationStatus.NOT_LACTATING);

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }

            //-Nipples reduction to 1 per tit.
            if (target.genitals.hasQuadNipples && Utils.Rand(4) == 0)
            {
                target.genitals.SetQuadNipples(false);

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }

            //-Remove extra breast rows
            if (target.breasts.Count > 1 && Utils.Rand(3) == 0 && !hyperHappy)
            {
                target.RemoveExtraBreastRows();
            }

            //-Butt > 5 - decrease butt size
            if (target.butt.size > 5 && Utils.Rand(4) == 0)
            {
                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }

                target.butt.ShrinkButt();
            }

            if (target.gender.HasFlag(Gender.FEMALE))
            {
                CupSize minCup = EnumHelper.Max(CupSize.D, target.genitals.smallestPossibleFemaleCupSize);
                //Breasts > D cup - Decrease breast size by up to 3 cups
                //MOD NOTE: Now respects minimum cup size from perks.
                if (target.gender.HasFlag(Gender.FEMALE) && target.genitals.BiggestCupSize() > minCup && Utils.Rand(3) == 0)
                {
                    foreach (Breasts breast in target.breasts)
                    {
                        if (breast.cupSize > CupSize.D)
                        {
                            breast.ShrinkBreasts((byte)(1 + Utils.Rand(3)));
                        }
                    }

                    target.IncreaseSpeed();

                    if (--remainingChanges <= 0)
                    {
                        return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                    }
                }

                //Breasts < B cup - Increase breast size by 1 cup
                if (target.gender.HasFlag(Gender.FEMALE) && target.genitals.SmallestCupSize() < CupSize.B && Utils.Rand(3) == 0)
                {
                    for (int i = 0; i < target.breasts.Count; i++)
                    {
                        if (target.breasts[i].cupSize < CupSize.B)
                        {
                            target.breasts[i].GrowBreasts();
                        }
                    }
                    target.ChangeLibido(1);
                    if (--remainingChanges <= 0)
                    {
                        return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                    }
                }

                //Hips > 12 - decrease hip size by 1-3 sizes
                if (target.hips.size > 12 && Utils.Rand(3) == 0)
                {
                    target.hips.ShrinkHips((byte)(1 + Utils.Rand(3)));
                    if (--remainingChanges <= 0)
                    {
                        return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                    }
                }

                //Hips < 6 - increase hip size by 1-3 sizes
                if (target.hips.size < 6 && Utils.Rand(3) == 0)
                {
                    target.hips.GrowHips((byte)(1 + Utils.Rand(3)));
                    if (--remainingChanges <= 0)
                    {
                        return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                    }
                }

                if (target.genitals.nippleLength > 1 && Utils.Rand(3) == 0)
                {
                    target.genitals.SetNippleLength(target.genitals.nippleLength / 2);
                }

                VaginalWetness desiredWetness = EnumHelper.Min(target.genitals.maxVaginalWetness, VaginalWetness.SLICK);
                //MOD NOTE: now respects all vaginas, and the maximum wetness allowed by perks (if applicable)
                if (target.hasVagina && target.genitals.SmallestVaginalWetness() < desiredWetness && Utils.Rand(4) == 0)
                {
                    foreach (V****a vag in target.vaginas)
                    {
                        if (vag.wetness < desiredWetness)
                        {
                            vag.IncreaseWetness();
                        }
                    }
                    if (--remainingChanges <= 0)
                    {
                        return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                    }
                }

                //Increase tone (up to 65)
                if (target.build.muscleTone < 65 && Utils.Rand(3) == 0)
                {
                    target.build.ChangeMuscleToneToward(65, 2);
                }

                //Decrease thickness (down to 35)
                if (target.build.thickness > 35 && Utils.Rand(3) == 0)
                {
                    target.build.ChangeThicknessToward(35, 5);
                }
                //Grant oviposition.
                if (target.womb.canObtainOviposition && Species.COCKATRICE.Score(target) > 3 && Utils.Rand(5) == 0)
                {
                    target.womb.GrantOviposition();
                    sb.Append(GrantOvipositionText(target));

                    if (--remainingChanges <= 0)
                    {
                        return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                    }
                }
            }

            if (target.gender == Gender.MALE)
            {
                //Breasts > B cup - decrease by 1 cup size
                if (target.genitals.BiggestCupSize() > CupSize.B && Utils.Rand(3) == 0)
                {
                    for (int i = 0; i < target.breasts.Count; i++)
                    {
                        if (target.breasts[i].cupSize > CupSize.B)
                        {
                            target.breasts[i].ShrinkBreasts();
                        }
                    }

                    target.IncreaseSpeed();

                    if (--remainingChanges <= 0)
                    {
                        return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                    }
                }

                if (target.genitals.nippleLength > 1 && Utils.Rand(3) == 0)
                {
                    target.genitals.SetNippleLength(target.genitals.nippleLength / 2);
                }

                //Hips > 10 - decrease hip size by 1-3 sizes
                if (target.hips.size > 10 && Utils.Rand(3) == 0)
                {
                    target.hips.ShrinkHips((byte)(1 + Utils.Rand(3)));
                    if (--remainingChanges <= 0)
                    {
                        return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                    }
                }

                //Hips < 2 - increase hip size by 1-3 sizes
                if (target.hips.size < 2 && Utils.Rand(3) == 0)
                {
                    target.hips.GrowHips((byte)(1 + Utils.Rand(3)));
                    if (--remainingChanges <= 0)
                    {
                        return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                    }
                }

                //Increase tone (up to 70)
                if (target.build.muscleTone < 70 && Utils.Rand(3) == 0)
                {
                    target.build.ChangeMuscleToneToward(70, 2);
                }

                //Decrease thickness (down to 35)
                if (target.build.thickness > 35 && Utils.Rand(3) == 0)
                {
                    target.build.ChangeThicknessToward(35, 5);
                }
            }

            if (target.gender.HasFlag(Gender.MALE))
            {
                //C**k < 6 inches - increase by 1-2 inches
                C**k shortest = target.genitals.ShortestCock();
                if (shortest.length < 6 && Utils.Rand(3) == 0)
                {
                    double increment = shortest.IncreaseLength(1 + Utils.Rand(2));

                    if (--remainingChanges <= 0)
                    {
                        return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                    }
                }

                C**k longest = target.genitals.LongestCock();
                //Shrink oversized cocks
                if (longest.length > 16 && Utils.Rand(3) == 0)
                {
                    longest.DecreaseLength((Utils.Rand(10) + 5) / 10.0);
                    if (longest.girth > 3)
                    {
                        longest.DecreaseThickness((Utils.Rand(4) + 1) / 10.0);
                    }
                    if (--remainingChanges <= 0)
                    {
                        return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                    }
                }

                C**k thinnest = target.genitals.ThinnestCock();
                //C**k thickness <2 - Increase c**k thickness
                if (thinnest.girth < 2 && Utils.Rand(3) == 0)
                {
                    thinnest.IncreaseThickness(1.5);

                    if (--remainingChanges <= 0)
                    {
                        return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                    }
                }
            }
            int lizardCocks = target.genitals.CountCocksOfType(CockType.LIZARD);

            if (target.hasCock && target.cocks.Count > lizardCocks && Utils.Rand(4) == 0)
            {
                //-Lizard dick - first one
                if (lizardCocks == 0)
                {
                    //Actually xform it nau
                    if (target.genitals.hasSheath)
                    {
                        target.genitals.UpdateCock(0, CockType.LIZARD);
                    }
                    else
                    {
                        target.genitals.UpdateCock(0, CockType.LIZARD);
                    }

                    if (--remainingChanges <= 0)
                    {
                        return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                    }

                    target.DeltaCreatureStats(lib: 3, lus: 10);
                }
                //(CHANGE OTHER DICK)
                //Requires 1 lizard c**k, multiple cocks
                else                 //if (target.cocks.Count > 1 && target.cocks.Count > lizardCocks)
                {
                    C**k firstNonLizard = target.cocks.First(x => x.type != CockType.LIZARD);

                    target.genitals.UpdateCock(firstNonLizard, CockType.LIZARD);

                    if (--remainingChanges <= 0)
                    {
                        return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                    }

                    target.DeltaCreatureStats(lib: 3, lus: 10);
                }
            }

            //MOD NOTE: Worms are being removed??? from the game due to that absolutely shitty license that prevents me from porting any content 'created' by
            //its creator (forget the name at this time). it's a bad license because it takes credit from other content creators that use its content. that's like saying
            //the creator of the rubber tire gets credit for all modern car designs. that's bullshit. of course cars require tires, and the original copyright required users
            //to pay a licensing fee for their use. that didn't grant the copyright holder for rubber tires the credit for the cars that used them. If anyone wants to get ahold
            //of the og worms creator and get him/her to relax that requirement to make it reasonable (and future content-change/port friendly), we'll see. until then, this is
            //removed.

            //For the record, that would grant him creator's credit on this document. which he/she had no input on. that's not right. and, by extension, the inventory system, since
            //this item is in use in the inventory system. and the time engine, because worms regen over time. I am the content creator for both of those, and i refuse to allow him/her
            //any credit for either of those. those took time and effort and were difficult - i'm not freely handing credit to him/her because that license would require me to. Either
            //his/her license changes, or the offending content is removed, or the entire game engine goes. Right now i think it's better go with the game engine because it make all of
            //this shit work. - JSG.

            ////--Worms leave if 100% lizard dicks?
            ////Require mammals?
            //if (target.genitals.CountCocksOfType(CockType.LIZARD) == target.cocks.Count && target.hasStatusEffect(StatusEffects.Infested))
            //{
            //	if (target.balls.count > 1)
            //	target.removeStatusEffect(StatusEffects.Infested);
            //	if (--remainingChanges <= 0) return ApplyChangesAndReturn(target, sb, changeCount - remainingChanges);
            //}

            //Increase height up to 5ft 7in.
            if (target.build.heightInInches < 67 && Utils.Rand(5) == 0)
            {
                target.build.IncreaseHeight((byte)(Utils.Rand(3) + 1));
                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }

            //Decrease height down to a maximum of 6ft 8in.
            if (target.build.heightInInches > 80 && Utils.Rand(5) == 0)
            {
                target.build.DecreaseHeight((byte)(Utils.Rand(3) + 1));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }

            //Physical changes:
            //Removes other antennae
            if (target.antennae.type != AntennaeType.COCKATRICE && !target.antennae.isDefault && Utils.Rand(3) == 0)
            {
                target.RestoreAntennae();
            }
            //Gain antennae like feathers
            if (target.antennae.type == AntennaeType.NONE && target.face.type == FaceType.COCKATRICE && target.ears.type == EarType.COCKATRICE && Utils.Rand(3) == 0)
            {
                // Other antennae types are handled above! (Stadler76)
                AntennaeData oldData = target.antennae.AsReadOnlyData();
                target.UpdateAntennae(AntennaeType.COCKATRICE);
                sb.Append(UpdateAntennaeText(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));
                }
            }

            //Face TF
            if (target.face.type != FaceType.COCKATRICE && target.arms.type == ArmType.COCKATRICE && target.lowerBody.type == LowerBodyType.COCKATRICE && Utils.Rand(3) == 0)
            {
                FaceData oldData = target.face.AsReadOnlyData();
                target.UpdateFace(FaceType.COCKATRICE);
                sb.Append(UpdateFaceText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Hair TF
            if (target.hair.type != HairType.FEATHER && Utils.Rand(4) == 0)
            {
                HairData oldData = target.hair.AsReadOnlyData();
                target.UpdateHair(HairType.FEATHER);
                sb.Append(UpdateHairText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Eye TF
            if (target.eyes.type != EyeType.COCKATRICE && target.face.type == FaceType.COCKATRICE && target.body.type == BodyType.COCKATRICE && target.ears.type == EarType.COCKATRICE &&
                Utils.Rand(3) == 0)
            {
                EyeData oldData = target.eyes.AsReadOnlyData();
                target.UpdateEyes(EyeType.COCKATRICE);
                sb.Append(UpdateEyesText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Lizard tongue TF
            if (target.tongue.type != TongueType.LIZARD && target.face.type == FaceType.COCKATRICE && Utils.Rand(3) == 0)
            {
                TongueData oldData = target.tongue.AsReadOnlyData();
                target.UpdateTongue(TongueType.LIZARD);
                sb.Append(UpdateTongueText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Ears TF
            if (target.ears.type != EarType.COCKATRICE && target.face.type == FaceType.COCKATRICE && Utils.Rand(3) == 0)
            {
                EarData oldData = target.ears.AsReadOnlyData();
                target.UpdateEars(EarType.COCKATRICE);
                sb.Append(UpdateEarsText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Arm TF
            if (target.arms.type != ArmType.COCKATRICE && Utils.Rand(4) == 0)
            {
                ArmData oldData = target.arms.AsReadOnlyData();
                target.UpdateArms(ArmType.COCKATRICE);
                sb.Append(UpdateArmsText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Neck loss, if not cockatrice neck
            if (target.neck.type != NeckType.COCKATRICE && 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.type != BackType.NORMAL && 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));
                }
            }
            //Body TF
            if (target.body.type != BodyType.COCKATRICE && target.face.type == FaceType.COCKATRICE && Utils.Rand(3) == 0)
            {
                Species.COCKATRICE.GetRandomCockatriceColors(out FurColor feathers, out Tones scales);

                target.UpdateBody(BodyType.COCKATRICE, feathers, scales);
                NeckData oldData = target.neck.AsReadOnlyData();
                target.UpdateNeck(NeckType.COCKATRICE, feathers.primaryColor);
                sb.Append(UpdateNeckText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Neck TF, if not already TFed from Body TF above
            if (target.neck.type != NeckType.COCKATRICE && target.body.type == BodyType.COCKATRICE && target.face.type == FaceType.COCKATRICE && Utils.Rand(3) == 0)
            {
                NeckData oldData = target.neck.AsReadOnlyData();
                target.UpdateNeck(NeckType.COCKATRICE, Utils.RandomChoice(Species.COCKATRICE.availablePrimaryFeatherColors));
                sb.Append(UpdateNeckText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Leg TF
            if (target.lowerBody.type != LowerBodyType.COCKATRICE && Utils.Rand(4) == 0)
            {
                LowerBodyData oldData = target.lowerBody.AsReadOnlyData();
                target.UpdateLowerBody(LowerBodyType.COCKATRICE);
                sb.Append(UpdateLowerBodyText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Tail TF
            if (target.tail.type != TailType.COCKATRICE && Utils.Rand(4) == 0)
            {
                TailData oldData = target.tail.AsReadOnlyData();
                target.UpdateTail(TailType.COCKATRICE);
                sb.Append(UpdateTailText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Wings TF
            //feathered wings and not large and a target? that shouldn't happen. silently make them large
            if (target.wings.type == WingType.FEATHERED && !target.wings.isLarge && target is Player)
            {
                target.wings.GrowLarge();
            }
            else if (target.wings.type != WingType.FEATHERED && target.arms.type == ArmType.COCKATRICE && Utils.Rand(4) == 0)
            {
                HairFurColors wingColor = !target.body.activeFur.isEmpty ? target.body.activeFur.fur.primaryColor : target.hair.hairColor;

                WingData oldData = target.wings.AsReadOnlyData();
                target.UpdateWings(WingType.FEATHERED);
                sb.Append(UpdateWingsText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }

            //FAILSAFE CHANGE
            if (remainingChanges == changeCount)
            {
                if (target is CombatCreature failSafe)
                {
                    failSafe.AddHP(50);
                }
                target.ChangeLust(3);
            }

            //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 VaginaCreator(double?clitLengthInInches         = null, VaginalWetness vaginalWetness = VaginalWetness.NORMAL,
                      VaginalLooseness vaginalLooseness = VaginalLooseness.TIGHT, bool omnibusClit = false, bool isVirgin = true,
                      Dictionary <ClitPiercingLocation, PiercingJewelry> clitJewelry = null, Dictionary <LabiaPiercingLocation, PiercingJewelry> labiaJewelry = null)
     : this(VaginaType.HUMAN, clitLengthInInches, vaginalWetness, vaginalLooseness, omnibusClit, isVirgin, clitJewelry, labiaJewelry)
 {
 }
Beispiel #8
0
        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.
            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.


            //STATS CHANGURYUUUUU
            //Boost speed (max 80!)
            if (Utils.Rand(3) == 0 && target.relativeSpeed < 80)
            {
                target.DeltaCreatureStats(spe: target.relativeSpeed < 35 ? 2 : 1);
            }
            //Boost libido
            if (Utils.Rand(5) == 0)
            {
                target.DeltaCreatureStats(lib: 1, lus: (5 + target.libido / 7));
                if (target.relativeLibido < 30)
                {
                    target.ChangeLibido(1);
                }

                if (target.relativeLibido < 40)
                {
                    target.ChangeLibido(1);
                }

                if (target.relativeLibido < 60)
                {
                    target.ChangeLibido(1);
                }
                //Lower ones are gender specific for some reason
            }

            //BIG sensitivity gains to 60.
            if (target.relativeSensitivity < 60 && Utils.Rand(3) == 0)
            {
                //(low)
                if (Utils.Rand(3) != 2)
                {
                    target.ChangeSensitivity(5);
                }
                //(BIG boost 1/3 chance)
                else
                {
                    target.ChangeSensitivity(15);
                }
            }


            //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);


            //Makes girls very girl(90), guys somewhat girly (61).
            if (Utils.Rand(2) == 0)
            {
                short res = target.femininity.ChangeFemininityToward((byte)(target.gender.HasFlag(Gender.FEMALE) ? 90 : 61), 4);
                if (res != 0)
                {
                    if (--remainingChanges <= 0)
                    {
                        return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                    }
                }
            }

            //De-wettification of c**t (down to 3?)!
            VaginalWetness targetWetness = EnumHelper.Max(target.genitals.minVaginalWetness, VaginalWetness.SLICK);

            if (target.hasVagina && target.genitals.SmallestVaginalWetness() > targetWetness && Utils.Rand(3) == 0)
            {
                //Just to be safe
                foreach (V****a vag in target.vaginas)
                {
                    vag.DecreaseWetness();
                }

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Fertility boost!
            if (Utils.Rand(4) == 0 && target.fertility.totalFertility < 50 && target.hasVagina)
            {
                target.fertility.IncreaseFertility((byte)(2 + Utils.Rand(5)));
                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //-VAGs
            //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));
                }
            }

            //MOD: Bunny eggs and oviposition are now one and the same. the idea of removing oviposition and adding bunny eggs - that's just dumb.
            if (target.womb.canObtainOviposition && Utils.Rand(4) == 0)
            {
                target.womb.GrantOviposition();
                sb.Append(GrantOvipositionText(target));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Shrink Balls!
            if (target.balls.count > 0 && target.balls.size > 5 && Utils.Rand(3) == 0)
            {
                if (target.balls.size < 10)
                {
                    target.balls.ShrinkBalls();
                }
                else if (target.balls.size < 25)
                {
                    target.balls.ShrinkBalls((byte)(2 + Utils.Rand(3)));
                }
                else
                {
                    target.balls.ShrinkBalls((byte)(6 + Utils.Rand(3)));
                }
                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Get rid of extra balls
            if (target.balls.count > 2 && Utils.Rand(3) == 0)
            {
                target.balls.RemoveExtraBalls();

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Boost cum production
            if ((target.balls.count > 0 || target.hasCock) && target.genitals.totalCum < 3000 && Utils.Rand(3) == 0)
            {
                target.genitals.IncreaseCumMultiplier(3 + Utils.Rand(7));

                if (target.genitals.totalCum >= 250)
                {
                    target.ChangeLust(3);
                }
                else if (target.genitals.totalCum >= 750)
                {
                    target.ChangeLust(4);
                }
                else if (target.genitals.totalCum >= 2000)
                {
                    target.ChangeLust(5);
                }

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Bunny feet! - requirez earz
            if (target.lowerBody.type != LowerBodyType.BUNNY && Utils.Rand(5) == 0 && target.ears.type == EarType.BUNNY)
            {
                LowerBodyData oldData = target.lowerBody.AsReadOnlyData();
                target.UpdateLowerBody(LowerBodyType.BUNNY);
                sb.Append(UpdateLowerBodyText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //BUN FACE! REQUIREZ EARZ
            if (target.ears.type == EarType.BUNNY && target.face.type != FaceType.BUNNY && Utils.Rand(3) == 0)
            {
                FaceData oldData = target.face.AsReadOnlyData();
                target.UpdateFace(FaceType.BUNNY);
                sb.Append(UpdateFaceText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            else if (target.ears.type == EarType.BUNNY && target.face.type == FaceType.BUNNY && !target.face.isFullMorph && Utils.Rand(3) == 0)
            {
                target.face.StrengthenFacialMorph();

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }

            //DAH BUNBUN EARZ - requires poofbutt!
            if (target.ears.type != EarType.BUNNY && Utils.Rand(3) == 0 && target.tail.type == TailType.RABBIT)
            {
                EarData oldData = target.ears.AsReadOnlyData();
                target.UpdateEars(EarType.BUNNY);
                sb.Append(UpdateEarsText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //DAH BUNBUNTAILZ
            if (target.tail.type != TailType.RABBIT && Utils.Rand(2) == 0)
            {
                TailData oldData = target.tail.AsReadOnlyData();
                target.UpdateTail(TailType.RABBIT);
                sb.Append(UpdateTailText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            // Remove gills
            if (Utils.Rand(4) == 0 && !target.gills.isDefault)
            {
                target.RestoreGills();
            }
            // 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 wings
            if ((target.wings.type != WingType.NONE || target.back.type == BackType.SHARK_FIN) && Utils.Rand(4) == 0)
            {
                target.RestoreWings();
                BackData oldData = target.back.AsReadOnlyData();
                target.RestoreBack();
                sb.Append(RestoredBackText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }

            //Bunny Breeder Perk?
            //FAILSAAAAFE
            if (remainingChanges == changeCount)
            {
                if (target.relativeLibido < 100)
                {
                    if (--remainingChanges <= 0)
                    {
                        return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                    }
                }

                target.DeltaCreatureStats(lib: 1, lus: (5 + target.libido / 7));
                if (target.relativeLibido < 30)
                {
                    target.ChangeLibido(1);
                }

                if (target.relativeLibido < 40)
                {
                    target.ChangeLibido(1);
                }

                if (target.relativeLibido < 60)
                {
                    target.ChangeLibido(1);
                }
            }


            //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));
        }