Esempio n. 1
0
        //5. Is a mammal that moves, sleeps, eats

        public Rabbit(string name, EyesColor eyes, FurColor fur, Genders gender, DateTime birthDate)
        {
            this.name = name;
            Eyes      = eyes;
            Fur       = fur;
            Gender    = gender;
            BirthDate = birthDate;
        }
Esempio n. 2
0
 public Rabbit(EyesColor eyesColor, FurColor furColor, Gender gender, DateTime birthDate, Owner owner)
 {
     this.eyesColor = eyesColor;
     this.furColor  = furColor;
     this.gender    = gender;
     this.birthDate = birthDate;
     this.owner     = owner;
 }
Esempio n. 3
0
 public Dog(string dogName, EyesColor eyesColor, FurColor furColor, Gender gender, DateTime birthDate, Owner owner)
 {
     this.dogName   = dogName;
     this.eyesColor = eyesColor;
     this.furColor  = furColor;
     this.gender    = gender;
     this.birthDate = birthDate;
     this.owner     = owner;
 }
Esempio n. 4
0
 internal static FurColor GetValidFurColor(FurColor overrideColor, FurColor primary, FurColor secondary, HairFurColors activeHairColor, FurColor fallback)
 {
     if (!FurColor.IsNullOrEmpty(overrideColor))
     {
         return(overrideColor);
     }
     else if (!FurColor.IsNullOrEmpty(secondary))
     {
         return(secondary);
     }
     else if (!FurColor.IsNullOrEmpty(primary))
     {
         return(primary);
     }
     else if (!HairFurColors.IsNullOrEmpty(activeHairColor))
     {
         return(new FurColor(activeHairColor));
     }
     return(fallback);
 }
        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));
        }
Esempio n. 6
0
 public override int GetHashCode()
 {
     unchecked
     {
         return(((EyeColor != null ? EyeColor.GetHashCode() : 0) * 397) ^ (FurColor != null ? FurColor.GetHashCode() : 0));
     }
 }
Esempio n. 7
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 }, 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));
        }
Esempio n. 8
0
 protected Animal(FurColor furColor, string name)
 {
     FurColor = furColor;
     Name     = name;
 }
Esempio n. 9
0
 internal static FurColor GetValidFurColor(FurColor overrideColor, FurColor primary, HairFurColors activeHairColor, FurColor fallback)
 {
     return(GetValidFurColor(overrideColor, primary, null, activeHairColor, fallback));
 }
Esempio n. 10
0
 internal virtual FurColor ParseFurColor(FurColor current, in BodyData data)
 public Monkey(string name, FurColor furColor, int age) // конструктор
 {
     this.furColor = furColor;                          // this Казва да се използват нещата подадени в този конструктор
     this.name     = name;
     this.age      = age;
 }
Esempio n. 12
0
 public Mouse(int age, string name, FurColor furColor, int tailLength)
     : base(age, name)
 {
     this.FurColor   = furColor;
     this.TailLength = tailLength;
 }
Esempio n. 13
0
 public TomCat(string name, int age, FurColor furColor) : base(name, age, AnimalsSex.male, furColor)
 {
 }
Esempio n. 14
0
 public Dog(int age, string name, FurColor furColor)
     : base(age, name)
 {
     this.FurColor = furColor;
     this.DogTag   = "my name is " + name;
 }
        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);

            //use:

            //stat changes:
            //lose height + gain speed (42" height floor, no speed ceiling but no speed changes without height change)
            if (target.build.heightInInches >= 45 && Utils.Rand(3) == 0)
            {
                target.IncreaseSpeed();

                target.build.DecreaseHeight();
                if (target.build.heightInInches > 60)
                {
                    target.build.DecreaseHeight();
                }

                if (target.build.heightInInches > 70)
                {
                    target.build.DecreaseHeight();
                }

                if (target.build.heightInInches > 80)
                {
                    target.build.DecreaseHeight();
                }

                if (target.build.heightInInches > 90)
                {
                    target.build.DecreaseHeight(2);
                }

                if (target.build.heightInInches > 100)
                {
                    target.build.DecreaseHeight(2);
                }

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //lose tough
            if (target.relativeToughness > 50 && Utils.Rand(3) == 0)
            {
                target.ChangeToughness(-1);
                if (target.relativeToughness >= 75)
                {
                    target.ChangeToughness(-1);
                }

                if (target.relativeToughness >= 90)
                {
                    target.ChangeToughness(-1);
                }
            }

            //SEXYYYYYYYYYYY
            //vag-anal capacity up for non-goo (available after PC < 5 ft; capacity ceiling reasonable but not horse-like or gooey)
            if (target.build.heightInInches < 60 && (target.genitals.standardBonusAnalCapacity < 100 || (target.genitals.standardBonusVaginalCapacity < 100 && target.hasVagina)) && Utils.Rand(3) == 0)
            {
                //adds some lust
                target.ChangeLust(10 + target.sensitivity / 5);
                if (target.genitals.standardBonusVaginalCapacity < 100 && target.hasVagina)
                {
                    target.genitals.IncreaseBonusVaginalCapacity(5);
                }
                else
                {
                    target.genitals.IncreaseBonusAnalCapacity(5);
                }
                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //fem fertility up and heat (suppress if pregnant)
            //not already in heat (add heat and lust)
            if (!target.HasTimedEffect <Heat>() || target.GetTimedEffectData <Heat>().totalAddedLibido < 30 && Utils.Rand(2) == 0)
            {
                bool intensified = target.HasTimedEffect <Heat>();
                if (target.GoIntoHeat())
                {
                    if (intensified)
                    {
                        ////[(no mino cum in inventory)]
                        //if (!target.hasItem(consumables.MINOCUM))
                        //{
                        //}
                        ////(mino cum in inventory and non-horse, 100 lust)
                        //else
                        //{
                        //	//(consumes item, increment addiction/output addict message, small chance of mino preg, reduce lust)]");
                        //	target.minoCumAddiction(5);
                        //	target.knockUp(PregnancyStore.PREGNANCY_MINOTAUR, PregnancyStore.INCUBATION_MINOTAUR, 175);
                        //	ConsumableLib consumables = game.consumables;
                        //	target.consumeItem(consumables.MINOCUM);
                        //}
#warning Not Implemented: consume minotaur cum, or if you don't have it, go f**k a minotaur to get it, and immediately consume it. do whatever sex is required for getting it.
                    }
                    else
                    {
                        // Also make a permanent nudge.
                        target.fertility.IncreaseFertility();
                    }
                    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));
                }
            }
            //bodypart changes:
            //gain ears
            if (target.ears.type != EarType.MOUSE && Utils.Rand(4) == 0)
            {
                EarData oldData = target.ears.AsReadOnlyData();
                target.UpdateEars(EarType.MOUSE);
                sb.Append(UpdateEarsText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //gain tail
            //from no tail
            if (target.ears.type == EarType.MOUSE && target.tail.type != TailType.MOUSE && Utils.Rand(4) == 0)
            {
                //from other tail
                TailData oldData = target.tail.AsReadOnlyData();
                target.UpdateTail(TailType.MOUSE);
                sb.Append(UpdateTailText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //get teeth - from human, bunny, coonmask, or other humanoid teeth faces
            if (target.ears.type == EarType.MOUSE && target.face.isHumanoid && target.face.type != FaceType.MOUSE && Utils.Rand(4) == 0)
            {
                FaceData oldData = target.face.AsReadOnlyData();
                target.UpdateFace(FaceType.MOUSE);
                sb.Append(UpdateFaceText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //get mouse muzzle from mouse teeth or other muzzle
            if (target.body.IsFurBodyType() && target.face.hasMuzzle && Utils.Rand(4) == 0)
            {
                target.UpdateFace(FaceType.MOUSE);
                target.face.StrengthenFacialMorph();

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //get fur
            if (!target.body.IsFurBodyType() || (!target.body.mainEpidermis.fur.IsIdenticalTo(HairFurColors.BROWN) &&
                                                 !target.body.mainEpidermis.fur.IsIdenticalTo(HairFurColors.WHITE)) && Utils.Rand(4) == 0)
            {
                FurColor color;
                int      temp = Utils.Rand(10);
                if (temp < 8)
                {
                    color = new FurColor(HairFurColors.BROWN);
                }
                else
                {
                    color = new FurColor(HairFurColors.WHITE);
                }
                BodyData oldData = target.body.AsReadOnlyData();
                target.UpdateBody(BodyType.SIMPLE_FUR, color);
                sb.Append(UpdateBodyText(target, oldData));

                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));
        }
Esempio n. 16
0
 public Bear(FurColor furColor, string name, int weight) : base(furColor, name)
 {
     Weight = weight;
 }
Esempio n. 17
0
        static void Main(string[] args)
        {
            //doing this cause of static main
            var animals       = new AnimalsForSale();
            var listOfAnimals = animals.GetAnimals();

            //=======================================

            Console.WriteLine("What is the name of the animal? ");
            var resName = Console.ReadLine();

            Console.WriteLine("What color is the fur? (black/brown/white) ");
            var resFur = Console.ReadLine().ToLower();

            FurColor furColor = FurColor.Unspecified;

            switch (resFur)
            {
            case "black":
                furColor = FurColor.Black;
                break;

            case "brown":
                furColor = FurColor.Brown;
                break;

            case "white":
                furColor = FurColor.White;
                break;

            default:
                furColor = FurColor.Unspecified;
                break;
            }

            Console.WriteLine("What is the animal? (bear/lion)");
            var resType = Console.ReadLine().ToLower();

            if (resType == "bear")
            {
                Console.WriteLine("How much does the bear weigh? ");
                var resWeightString = Console.ReadLine();
                var resWeight       = Convert.ToInt32(resWeightString);

                var animal  = new Bear(furColor, resName, resWeight);
                var forSale = new ForSale(animal);
                listOfAnimals.Add(forSale);

                Console.WriteLine("The cost of the animal is: " + animals.CostOfAnimal);
            }
            else if (resType == "lion")
            {
                Console.WriteLine("How many cubs does the Lion have? ");
                var resCubsString = Console.ReadLine();
                var resCubs       = Convert.ToInt32(resCubsString);

                var animal  = new Lion(furColor, resName, resCubs);
                var forSale = new ForSale(animal);
                listOfAnimals.Add(forSale);

                Console.WriteLine("The cost of the animal is: " + animals.CostOfAnimal);
            }
        }
Esempio n. 18
0
 public Kitten(string name, int age, FurColor furColor) : base(name, age, AnimalsSex.female, furColor)
 {
 }
Esempio n. 19
0
 public Lion(FurColor furColor, string name, int numberOfCubs) : base(furColor, name)
 {
     NumberOfCubs = numberOfCubs;
 }
Esempio n. 20
0
        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));
        }
Esempio n. 21
0
 public Cats(string name, int age, AnimalsSex sex, FurColor furColor) : base(name, age, sex)
 {
     this.furColor = furColor;
 }
        //Original credits:
        //since March 26, 2018
        //@author Stadler76
        //
        //Porter's note: Nearly all of the comments here are from the vanilla. comments from modification of code will be marked with <MODIFICATION>
        protected internal override string DoTransformation(Creature target, out bool isBadEnd)
        {
            isBadEnd = false;
            //<MODIFICATION NOTE>
            //potent tf has an initial count of 3.
            int changeCount      = GenerateChangeCount(target, new int[] { 2, 2 }, enhanced ? 3 : 1);
            int remainingChanges = changeCount;

            StringBuilder sb = new StringBuilder();

            sb.Append(InitialTransformationText(target));

            if (target.face.type == FaceType.FOX && target.tail.type == TailType.FOX && target.ears.type == EarType.FOX && target.lowerBody.type == LowerBodyType.FOX &&
                target.body.IsFurBodyType() && Utils.Rand(3) == 0 && target is IExtendedCreature extended && !extended.extendedData.resistsTFBadEnds)
            {
                if (!extended.extendedData.hasFoxWarning)
                {
                    extended.extendedData.hasFoxWarning = true;
                }
                else
                {
                    isBadEnd = true;
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }

            //<MODIFICATION NOTE>
            //Free Changes.

            //[decrease Strength] (to some floor) // I figured 15 was fair, but you're in a better position to judge that than I am.
            if (Utils.Rand(3) == 0 && target.relativeStrength > 40)
            {
                if (target.relativeStrength > 90)
                {
                    target.DecreaseStrength(4);
                }
                else if (target.relativeStrength > 80)
                {
                    target.DecreaseStrength(3);
                }
                else if (target.relativeStrength > 60)
                {
                    target.DecreaseStrength(2);
                }
                else
                {
                    target.DecreaseStrength();
                }
            }
            //[decrease Toughness] (to some floor) // 20 or so was my thought here
            if (Utils.Rand(3) == 0 && target.relativeToughness > 30)
            {
                if (target.relativeToughness > 90)
                {
                    target.DecreaseToughness(4);
                }
                else if (target.relativeToughness > 80)
                {
                    target.DecreaseToughness(3);
                }
                else if (target.relativeToughness > 60)
                {
                    target.DecreaseToughness(2);
                }
                else
                {
                    target.DecreaseToughness();
                }
            }
            //[increase Intelligence, Libido and Sensitivity]
            if (Utils.Rand(3) == 0 && (target.relativeLibido < 80 || target.relativeSensitivity < 80 || target.relativeIntelligence < 80))
            {
                if (target.relativeIntelligence < 80)
                {
                    target.IncreaseIntelligence(4);
                }

                if (target.relativeLibido < 80)
                {
                    target.IncreaseLibido(1);
                }

                if (target.relativeSensitivity < 80)
                {
                    target.IncreaseSensitivity(1);
                }
                //gain small lust also
                target.IncreaseLust(10);
            }
            //Modification Note: move this free change up here, where it makes the most sense.
            if (target.build.muscleTone > 40 && Utils.Rand(2) == 0)
            {
                target.build.DecreaseMuscleTone(4);
            }


            if (!Species.FOX.AvailableHairColors.Contains(target.hair.hairColor) && !Species.KITSUNE.elderKitsuneHairColors.Contains(target.hair.hairColor) &&
                !Species.KITSUNE.kitsuneHairColors.Contains(target.hair.hairColor) && Utils.Rand(4) == 0)
            {
                HairFurColors targetColor;
                if (target.tail.type == TailType.FOX && target.tail.tailCount > 1)
                {
                    if (target.tail.tailCount < 9)
                    {
                        targetColor = Utils.RandomChoice(Species.KITSUNE.kitsuneHairColors);
                    }

                    targetColor = Utils.RandomChoice(Species.KITSUNE.elderKitsuneHairColors);
                }
                else
                {
                    targetColor = Utils.RandomChoice(Species.FOX.AvailableHairColors);
                }
            }

            //this will handle the edge case where the change count starts out as 0.
            if (remainingChanges <= 0)
            {
                return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
            }

            //<MODIFICATION NOTE>
            //Transformation Changes.
            //if (--remainingChanges <= 0) return ApplyChangesAndReturn(target, sb, changeCount - remainingChanges);

            //[Adjust hips toward 10 – wide/curvy/flared]
            if (Utils.Rand(3) == 0 && target.hips.size != 10)
            {
                //from narrow to wide
                if (target.hips.size < 7)
                {
                    target.hips.GrowHips(2);
                }
                else if (target.hips.size < 10)
                {
                    target.hips.GrowHips();
                }
                //from wide to narrower
                else if (target.hips.size > 13)
                {
                    target.hips.ShrinkHips(2);
                }
                else
                {
                    target.hips.ShrinkHips();
                }

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //[Remove tentacle hair]
            //required if the hair length change below is triggered
            if (target.hair.type == HairType.ANEMONE && Utils.Rand(3) == 0)
            {
                //-insert anemone hair removal into them under whatever criteria you like, though hair removal should precede abdomen growth;
                HairData oldData = target.hair.AsReadOnlyData();
                target.RestoreHair();
                sb.Append(RestoredHairText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //[Adjust hair length toward range of 16-26 – very long to ass-length]
            if (target.hair.type == HairType.ANEMONE && (target.hair.length > 26 || target.hair.length < 16) && target.hair.canGrowNaturally && Utils.Rand(4) == 0)
            {
                if (target.hair.length < 16)
                {
                    target.hair.GrowHair(1 + Utils.Rand(4));
                }
                else
                {
                    target.hair.ShortenHair(1 + Utils.Rand(4));
                }

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            if (Utils.Rand(10) == 0)
            {
                //MOD NOTE: Don't remove ?. operator.
                if ((target as CombatCreature)?.RecoverFatigue(10) > 0)
                {
                    if (--remainingChanges <= 0)
                    {
                        return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                    }
                }
            }

            //dog cocks!

            //MOD NOTE: consider adding back in fox cocks and using them? they could literally just be dog cocks but with a slightly different text descriptions.
            //MOD NOTE: this is a linq check that sees if any available cocks aren't a dog c**k. it's actually faster than count of type, because it stops as soon as it hits
            //a c**k that isn't a dog, instead of checking all of them. Also, this function finds all non-dog cocks and converts one at random.
            if (Utils.Rand(3) == 0 && target.hasCock && target.cocks.Any(x => x.type != CockType.DOG))
            {
                C**k toChange = Utils.RandomChoice(target.cocks.Where(x => x.type != CockType.DOG).ToArray());

                if (toChange.type == CockType.HUMAN)
                {
                    toChange.IncreaseThickness(.3);
                    target.DeltaCreatureStats(sens: 10, lus: 5);
                }
                //Horse
                else if (toChange.type == CockType.HORSE)
                {
                    //Tweak length/thickness.

                    double deltaLength;
                    if (toChange.length > 6)
                    {
                        deltaLength = -2;
                    }
                    else
                    {
                        deltaLength = -.5;
                    }

                    toChange.SetLengthAndGirth(toChange.length + deltaLength, toChange.girth + 0.5);
                    target.DeltaCreatureStats(sens: 4, lus: 5);
                }
                else
                {
                    target.DeltaCreatureStats(sens: 4, lus: 10);
                }

                target.genitals.UpdateCock(toChange, CockType.DOG);

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

            //Cum Multiplier Xform
            if (target.genitals.totalCum < 5000 && Utils.Rand(3) == 0 && target.hasCock)
            {
                int temp = 2 + Utils.Rand(4);
                //Lots of cum raises cum multiplier cap to 2 instead of 1.5
                if (target.HasPerk <MessyOrgasms>())
                {
                    temp += Utils.Rand(10);
                }
                //MOD NOTE: not sure if cum calculations changed, (i think they have) and if so, that's a lot of multiplier gain holy shit. meh. whatever.
                target.genitals.IncreaseCumMultiplier(temp);
                //Flavor text
                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            if (target.balls.count > 0 && target.balls.size > 4 && Utils.Rand(3) == 0)
            {
                int targetSize;
                //currently above max, but whatever, that'll probably get raised anyway.
                if (target.balls.size > 50)
                {
                    targetSize = target.balls.size / 5;
                }
                else if (target.balls.size > 10)
                {
                    targetSize = target.balls.size / 2;
                }
                else
                {
                    targetSize = target.balls.size - 1;
                }

                //allow perks to work.
                target.balls.ShrinkBalls((byte)(target.balls.size - targetSize));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Sprouting more!
            if (enhanced && target.breasts.Count < 4 && target.breasts[target.breasts.Count - 1].cupSize > CupSize.A)
            {
                target.genitals.AddBreastRow(target.breasts[target.breasts.Count - 1].cupSize);

                target.DeltaCreatureStats(sens: 2, lus: 30);

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Find out if t**s are eligible for evening
            //MOD NOTE: there's an easier way - just run the normalize breasts. it'll return true if it changed anything. since we display the results of the old
            //breast data anyway, this is way simpler. Also, normalize breasts now returns a bool. woo!
            //MOD NOTE 2: Fox rules here seem to use the same size as previous. if they want to function under anthro rules (size is in decreasing order, but otherwise
            //roughly even) you can use AnthropomorphizeBreasts() instead. see canine tfs for an example.
            if (target.genitals.NormalizeBreasts())
            {
                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }



            //HEAT!
            if (!target.HasTimedEffect <Heat>() || target.GetTimedEffectData <Heat>().totalAddedLibido < 30 && Utils.Rand(6) == 0)
            {
                target.GoIntoHeat();

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //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)
            {
                if (target.womb.ClearOviposition())
                {
                    if (--remainingChanges <= 0)
                    {
                        return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                    }
                }
            }
            //[Grow Fur]
            //FOURTH
            //MOD NOTE: Body has been reworked since this was written, we'll allow kitsune's to remain unchanged, but all others need to be full fur after this.
            if ((enhanced || target.lowerBody.type == LowerBodyType.FOX) && target.body.type != BodyType.KITSUNE && !target.body.IsFurBodyType() && Utils.Rand(4) == 0)
            {
                BodyData oldBodyData = target.body.AsReadOnlyData();

                if (Species.KITSUNE.Score(target) >= 4)
                {
                    FurColor[] colorChoices;
                    if (Species.KITSUNE.elderKitsuneFurColors.Any(x => x.IsIdenticalTo(target.hair.hairColor)) ||
                        Species.KITSUNE.allKitsuneColors.Any(y => y.IsIdenticalTo(target.hair.hairColor)))
                    {
                        colorChoices = new FurColor[] { new FurColor(target.hair.hairColor) };
                    }
                    else if (target.tail.type == TailType.FOX && target.tail.tailCount == TailType.FOX.maxTailCount)
                    {
                        colorChoices = Species.KITSUNE.allKitsuneColors;
                    }
                    else
                    {
                        colorChoices = Species.KITSUNE.elderKitsuneFurColors;
                    }

                    target.UpdateBody(BodyType.UNDERBODY_FUR, Utils.RandomChoice(colorChoices));
                }
                else
                {
                    Species.FOX.GetRandomFurColors(out FurColor primary, out FurColor underbody);

                    target.UpdateBody(BodyType.UNDERBODY_FUR, primary, underbody);
                }

                //should always be true, but whatever.
                if (oldBodyData.type != target.body.type)
                {
                    remainingChanges--;
                    if (remainingChanges <= 0)
                    {
                        return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                    }
                }
            }
            //[Grow Fox Legs]
            //THIRD
            if ((enhanced || target.ears.type == EarType.FOX) && target.lowerBody.type != LowerBodyType.FOX && Utils.Rand(5) == 0)
            {
                LowerBodyData oldData = target.lowerBody.AsReadOnlyData();
                target.UpdateLowerBody(LowerBodyType.FOX);
                sb.Append(UpdateLowerBodyText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Grow Fox Ears]
            //SECOND
            if ((enhanced || target.tail.type == TailType.FOX) && target.ears.type != EarType.FOX && Utils.Rand(4) == 0)
            {
                EarData oldData = target.ears.AsReadOnlyData();
                target.UpdateEars(EarType.FOX);
                sb.Append(UpdateEarsText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //[Grow Fox Tail](fairly common)
            //FIRST
            if (target.tail.type != TailType.FOX && Utils.Rand(4) == 0)
            {
                TailData oldData = target.tail.AsReadOnlyData();
                target.UpdateTail(TailType.FOX);
                sb.Append(UpdateTailText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //[Grow Fox Face]
            //LAST - muzzlygoodness
            //should work from any face, including other muzzles
            if (target.body.HasAny(EpidermisType.FUR) && target.face.type != FaceType.FOX && Utils.Rand(5) == 0)
            {
                FaceData oldData = target.face.AsReadOnlyData();
                target.UpdateFace(FaceType.FOX);
                sb.Append(UpdateFaceText(target, oldData));

                if (--remainingChanges <= 0)
                {
                    return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
                }
            }
            //Arms
            if (target.arms.type != ArmType.FOX && target.body.HasAny(EpidermisType.FUR) && target.tail.type == TailType.FOX && target.lowerBody.type == LowerBodyType.FOX && Utils.Rand(4) == 0)
            {
                ArmData oldData = target.arms.AsReadOnlyData();
                target.UpdateArms(ArmType.FOX);
                sb.Append(UpdateArmsText(target, oldData));

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


            if (remainingChanges == changeCount && !(target is null))
            {
                (target as CombatCreature)?.RecoverFatigue(5);
            }

            //<MODIFICATION NOTE>
            //Fall through, cleanup and return.
            return(ApplyChangesAndReturn(target, sb, changeCount - remainingChanges));
        }